@database "exec"
@master "AMIDEV:NDK/Autodocs/exec.doc"

@Node Main "exec.doc"
@toc "Autodocs/AG/INDEX/Main"
    @{" AbortIO() " Link "AbortIO()"}
    @{" AddDevice() " Link "AddDevice()"}
    @{" AddHead() " Link "AddHead()"}
    @{" AddIntServer() " Link "AddIntServer()"}
    @{" AddLibrary() " Link "AddLibrary()"}
    @{" AddMemHandler() " Link "AddMemHandler()"}
    @{" AddMemList() " Link "AddMemList()"}
    @{" AddPort() " Link "AddPort()"}
    @{" AddResource() " Link "AddResource()"}
    @{" AddSemaphore() " Link "AddSemaphore()"}
    @{" AddTail() " Link "AddTail()"}
    @{" AddTask() " Link "AddTask()"}
    @{" Alert() " Link "Alert()"}
    @{" AllocAbs() " Link "AllocAbs()"}
    @{" Allocate() " Link "Allocate()"}
    @{" AllocEntry() " Link "AllocEntry()"}
    @{" AllocMem() " Link "AllocMem()"}
    @{" AllocPooled() " Link "AllocPooled()"}
    @{" AllocSignal() " Link "AllocSignal()"}
    @{" AllocTrap() " Link "AllocTrap()"}
    @{" AllocVec() " Link "AllocVec()"}
    @{" AttemptSemaphore() " Link "AttemptSemaphore()"}
    @{" AttemptSemaphoreShared() " Link "AttemptSemaphoreShared()"}
    @{" AvailMem() " Link "AvailMem()"}
    @{" CacheClearE() " Link "CacheClearE()"}
    @{" CacheClearU() " Link "CacheClearU()"}
    @{" CacheControl() " Link "CacheControl()"}
    @{" CachePostDMA() " Link "CachePostDMA()"}
    @{" CachePreDMA() " Link "CachePreDMA()"}
    @{" Cause() " Link "Cause()"}
    @{" CheckIO() " Link "CheckIO()"}
    @{" CloseDevice() " Link "CloseDevice()"}
    @{" CloseLibrary() " Link "CloseLibrary()"}
    @{" ColdReboot() " Link "ColdReboot()"}
    @{" CopyMem() " Link "CopyMem()"}
    @{" CopyMemQuick() " Link "CopyMemQuick()"}
    @{" CreateIORequest() " Link "CreateIORequest()"}
    @{" CreateMsgPort() " Link "CreateMsgPort()"}
    @{" CreatePool() " Link "CreatePool()"}
    @{" Deallocate() " Link "Deallocate()"}
    @{" Debug() " Link "Debug()"}
    @{" DeleteIORequest() " Link "DeleteIORequest()"}
    @{" DeleteMsgPort() " Link "DeleteMsgPort()"}
    @{" DeletePool() " Link "DeletePool()"}
    @{" Disable() " Link "Disable()"}
    @{" DoIO() " Link "DoIO()"}
    @{" Enable() " Link "Enable()"}
    @{" Enqueue() " Link "Enqueue()"}
    @{" FindName() " Link "FindName()"}
    @{" FindPort() " Link "FindPort()"}
    @{" FindResident() " Link "FindResident()"}
    @{" FindSemaphore() " Link "FindSemaphore()"}
    @{" FindTask() " Link "FindTask()"}
    @{" Forbid() " Link "Forbid()"}
    @{" FreeEntry() " Link "FreeEntry()"}
    @{" FreeMem() " Link "FreeMem()"}
    @{" FreePooled() " Link "FreePooled()"}
    @{" FreeSignal() " Link "FreeSignal()"}
    @{" FreeTrap() " Link "FreeTrap()"}
    @{" FreeVec() " Link "FreeVec()"}
    @{" GetCC() " Link "GetCC()"}
    @{" GetMsg() " Link "GetMsg()"}
    @{" InitCode() " Link "InitCode()"}
    @{" InitResident() " Link "InitResident()"}
    @{" InitSemaphore() " Link "InitSemaphore()"}
    @{" InitStruct() " Link "InitStruct()"}
    @{" Insert() " Link "Insert()"}
    @{" MakeFunctions() " Link "MakeFunctions()"}
    @{" MakeLibrary() " Link "MakeLibrary()"}
    @{" NewMinList() " Link "NewMinList()"}
    @{" ObtainQuickVector() " Link "ObtainQuickVector()"}
    @{" ObtainSemaphore() " Link "ObtainSemaphore()"}
    @{" ObtainSemaphoreList() " Link "ObtainSemaphoreList()"}
    @{" ObtainSemaphoreShared() " Link "ObtainSemaphoreShared()"}
    @{" OldOpenLibrary() " Link "OldOpenLibrary()"}
    @{" OpenDevice() " Link "OpenDevice()"}
    @{" OpenLibrary() " Link "OpenLibrary()"}
    @{" OpenResource() " Link "OpenResource()"}
    @{" Permit() " Link "Permit()"}
    @{" Procure() " Link "Procure()"}
    @{" PutMsg() " Link "PutMsg()"}
    @{" RawDoFmt() " Link "RawDoFmt()"}
    @{" ReleaseSemaphore() " Link "ReleaseSemaphore()"}
    @{" ReleaseSemaphoreList() " Link "ReleaseSemaphoreList()"}
    @{" RemDevice() " Link "RemDevice()"}
    @{" RemHead() " Link "RemHead()"}
    @{" RemIntServer() " Link "RemIntServer()"}
    @{" RemLibrary() " Link "RemLibrary()"}
    @{" RemMemHandler() " Link "RemMemHandler()"}
    @{" Remove() " Link "Remove()"}
    @{" RemPort() " Link "RemPort()"}
    @{" RemResource() " Link "RemResource()"}
    @{" RemSemaphore() " Link "RemSemaphore()"}
    @{" RemTail() " Link "RemTail()"}
    @{" RemTask() " Link "RemTask()"}
    @{" ReplyMsg() " Link "ReplyMsg()"}
    @{" SendIO() " Link "SendIO()"}
    @{" SetExcept() " Link "SetExcept()"}
    @{" SetFunction() " Link "SetFunction()"}
    @{" SetIntVector() " Link "SetIntVector()"}
    @{" SetSignal() " Link "SetSignal()"}
    @{" SetSR() " Link "SetSR()"}
    @{" SetTaskPri() " Link "SetTaskPri()"}
    @{" Signal() " Link "Signal()"}
    @{" StackSwap() " Link "StackSwap()"}
    @{" SumKickData() " Link "SumKickData()"}
    @{" SumLibrary() " Link "SumLibrary()"}
    @{" SuperState() " Link "SuperState()"}
    @{" Supervisor() " Link "Supervisor()"}
    @{" TypeOfMem() " Link "TypeOfMem()"}
    @{" UserState() " Link "UserState()"}
    @{" Vacate() " Link "Vacate()"}
    @{" Wait() " Link "Wait()"}
    @{" WaitIO() " Link "WaitIO()"}
    @{" WaitPort() " Link "WaitPort()"}
@EndNode

@Node "AbortIO()" "exec.library/AbortIO"

@{b}   NAME@{ub}
	AbortIO - attempt to abort an in-progress I/O request

@{b}   SYNOPSIS@{ub}
	AbortIO(iORequest)
	        A1

	VOID AbortIO(struct @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} *);

@{b}   FUNCTION@{ub}
	Ask a device to abort a previously started @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16}.  This is done
	by calling the device's AbortIO function, with your given @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16}.


	AbortIO is a command the device that may or may not grant.  If
	successful, the device will stop processing the @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16}, and
	reply to it earlier than it would otherwise have done.

@{b}   NOTE@{ub}
	AbortIO() does NOT @{"Remove()" Link "Remove()"} the @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} from your ReplyPort, OR
	wait for it to complete.  After an AbortIO() you must wait normally
	for the reply message before actually reusing the request.

	If a request has already completed when AbortIO() is called, no
	action is taken.

@{b}   EXAMPLE@{ub}
	    AbortIO(timer_request);
	    WaitIO(timer_request);
	    /* @{"Message" Link "INCLUDE:exec/ports.h/Main" 45} is free to be reused */

@{b}   INPUTS@{ub}
	iORequest - pointer to an I/O request block (must have been used
		at least once.  May be active or finished).

@{b}   SEE ALSO@{ub}
	@{"WaitIO" Link "exec/WaitIO()"}, @{"DoIO" Link "exec/DoIO()"}, @{"SendIO" Link "exec/SendIO()"}, @{"CheckIO" Link "exec/CheckIO()"}

@EndNode

@Node "AddDevice()" "exec.library/AddDevice"

@{b}   NAME@{ub}
	AddDevice -- add a device to the system

@{b}   SYNOPSIS@{ub}
	AddDevice(device)
		  A1

	void AddDevice(struct @{"Device" Link "INCLUDE:exec/devices.h/Main" 23} *);

@{b}   FUNCTION@{ub}
	This function adds a new device to the system device list, making
	it available to other programs.  The device must be ready to be
	opened at this time.

@{b}   INPUTS@{ub}
	device - pointer to a properly initialized device node

@{b}   SEE ALSO@{ub}
	@{"RemDevice" Link "exec/RemDevice()"}, @{"OpenDevice" Link "trackdisk/OpenDevice()"}, @{"CloseDevice" Link "serial/CloseDevice()"}, @{"MakeLibrary" Link "exec/MakeLibrary()"}

@EndNode

@Node "AddHead()" "exec.library/AddHead"

@{b}   NAME@{ub}
	AddHead -- insert node at the head of a list

@{b}   SYNOPSIS@{ub}
	AddHead(list, node)
		A0    A1

	void AddHead(struct @{"List" Link "INCLUDE:exec/lists.h/Main" 19} *, struct @{"Node" Link "INCLUDE:exec/nodes.h/Main" 21} *)

@{b}   FUNCTION@{ub}
	Add a node to the head of a doubly linked list. Assembly
	programmers may prefer to use the ADDHEAD macro from
	"exec/lists.i".

@{b}   WARNING@{ub}
	This function does not arbitrate for access to the list.  The
	calling task must be the owner of the involved list.

@{b}   INPUTS@{ub}
	list - a pointer to the target list header
	node - the node to insert at head

@{b}   SEE ALSO@{ub}
	@{"AddTail" Link "exec/AddTail()"}, @{"Enqueue" Link "exec/Enqueue()"}, @{"Insert" Link "exec/Insert()"}, @{"Remove" Link "exec/Remove()"}, @{"RemHead" Link "exec/RemHead()"}, @{"RemTail" Link "exec/RemTail()"}

@EndNode

@Node "AddIntServer()" "exec.library/AddIntServer"

@{b}   NAME@{ub}
	AddIntServer -- add an interrupt server to a system server chain

@{b}   SYNOPSIS@{ub}
	AddIntServer(intNum, interrupt)
		     D0-0:4  A1

	void AddIntServer(ULONG, struct @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} *);

@{b}   FUNCTION@{ub}
	This function adds a new interrupt server to a given server chain.
	The node is located on the chain in a priority dependent position.
	If this is the first server on a particular chain, interrupts will
	be enabled for that chain.

	Each link in the chain will be called in priority order until the
	chain ends or one of the servers returns with the 68000's Z condition
	code clear (indicating non-zero).  Servers on the chain should return
	with the Z flag clear if the interrupt was specifically for that
	server, and no one else.  VERTB servers should always return Z set.
	(Take care with High Level Language servers, the language may not
	have a mechanism for reliably setting the Z flag on exit).

	Servers are called with the following register conventions:

	    D0 - scratch
	    D1 - scratch

	    A0 - scratch
	    A1 - server is_Data pointer (scratch)

	    A5 - jump vector register (scratch)
	    A6 - scratch

	    all other registers must be preserved

@{b}   INPUTS@{ub}
	intNum - the Paula interrupt bit number (0 through 14). Processor
		 level seven interrupts (NMI) are encoded as intNum 15.
		 The PORTS, COPER, VERTB, EXTER and NMI interrupts are
		 set up as server chains.
	interrupt - pointer to an @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} structure.
		 By convention, the LN_NAME of the interrupt structure must
		 point a descriptive string so that other users may
		 identify who currently has control of the interrupt.

@{b}   WARNING@{ub}
	Some compilers or assemblers may optimize code in unexpected ways,
	affecting the conditions codes returned from the function.  Watch
	out for a "MOVEM" instruction (which does not affect the condition
	codes) turning into "MOVE" (which does).

@{b}   BUGS@{ub}
	The graphics library's VBLANK server, and some user code, currently
	assume that address register A0 will contain a pointer to the custom
	chips. If you add a server at a priority of 10 or greater, you must
	compensate for this by providing the expected value ($DFF000).

@{b}   SEE ALSO@{ub}
	@{"RemIntServer" Link "exec/RemIntServer()"}, @{"SetIntVector" Link "exec/SetIntVector()"}, hardware/intbits.i,exec/interrupts.i

@EndNode

@Node "AddLibrary()" "exec.library/AddLibrary"

@{b}   NAME@{ub}
	AddLibrary -- add a library to the system

@{b}   SYNOPSIS@{ub}
	AddLibrary(library)
		   A1

	void AddLibrary(struct @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} *);

@{b}   FUNCTION@{ub}
	This function adds a new library to the system, making it available
	to other programs.  The library should be ready to be opened at
	this time.  It will be added to the system library name list, and
	the checksum on the library entries will be calculated.

@{b}   INPUTS@{ub}
	library - pointer to a properly initialized library structure

@{b}   SEE ALSO@{ub}
	@{"RemLibrary" Link "exec/RemLibrary()"}, @{"CloseLibrary" Link "exec/CloseLibrary()"}, @{"OpenLibrary" Link "exec/OpenLibrary()"}, @{"MakeLibrary" Link "exec/MakeLibrary()"}

@EndNode

@Node "AddMemHandler()" "exec.library/AddMemHandler"

@{b}   NAME@{ub}
	AddMemHandler - Add a low memory handler to exec                 (V39)

@{b}   SYNOPSIS@{ub}
	AddMemHandler(memHandler)
	              A1

	VOID AddMemHandler(struct @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} *);

@{b}   FUNCTION@{ub}
	This function adds a low memory handler to the system.  The handler
	is described in the @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} structure.  Due to multitasking
	issues, the handler must be ready to run the moment this function
	call is made.  (The handler may be called before the call returns)

@{b}   NOTE@{ub}
	Adding a handler from within a handler will cause undefined
	actions.  It is safe to add a handler to the list while within
	a handler but the newly added handler may or may not be called
	for the specific failure currently running.

@{b}   EXAMPLE@{ub}
	struct @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} *myInt;  \* Assume it is allocated *\

	myInt->is_Node.ln_Pri=50;  \* Relatively early; before RAMLIB *\

	\* Please fill in the name field! *\
	myInt->is_Node.ln_Name="Example Handler";

	myInt->is_Data=(APTR)mydata_pointer;
	myInt->is_Code=myhandler_code;

	AddMemHandler(myInt);
	... \* and so on *\

	_myhandler_code:
			; This is the handler code
			; We are passed a pointer to struct @{"MemHandlerData" Link "INCLUDE:exec/memory.h/Main" 88}
			; in a0, the value of is_Data in a1 and
			; @{"ExecBase" Link "INCLUDE:exec/execbase.h/Main" 32} in a6.
			; We must not break forbid!!!
	;
	; Start off assuming we did nothing
	;
		moveq.l	#MEM_DID_NOTHING,d0
		move.l	memh_RequestFlags(a0),d1
		btst.l	#MEMB_CHIP,d1	; Did the failure happen in CHIP
		beq.s	handler_nop	; If not, we have nothing to do
		bsr	DoMyMagic	; Do the magic...
		; DoMyMagic frees whatever we can and returns d0 set...
	handler_nop:
		rts			; Return with d0 set...

@{b}   INPUTS@{ub}
	memHandler - A pointer to a completely filled in @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} structure
	             The priority field determine the position of the handler
	             with respect to other handlers in the system.  The higher
	             the priority, the earlier the handler is called.
	             Positive priorities will have the handler called before
	             any of the library expunge vectors are called.  Negative
	             priority handlers will be called after the library
	             expunge routines are called.
	             (Note:  RAMLIB is a handler at priority 0)

@{b}   SEE ALSO@{ub}
	@{"RemMemHandler" Link "exec/RemMemHandler()"}, exec/interrupts.i

@EndNode

@Node "AddMemList()" "exec.library/AddMemList"

@{b}   NAME@{ub}
	AddMemList - add memory to the system free pool

@{b}   SYNOPSIS@{ub}
	AddMemList( size, attributes, pri, base, name )
                     D0      D1        D2   A0    A1

	void AddMemList(ULONG, ULONG, @{"LONG" Link "INCLUDE:exec/types.h/Main" 112}, @{"APTR" Link "INCLUDE:exec/types.h/Main" 75}, STRPTR);

@{b}   FUNCTION@{ub}
	Add a new region of memory to the system free pool.  The first few
	bytes will be used to hold the @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26} structure.  The remainder
	will be made available to the rest of the world.

@{b}   INPUTS@{ub}
	size - the size (in bytes) of the memory area
	attributes - the attributes word that the memory pool will have
	pri  - the priority for this memory.  CHIP memory has a pri of -10,
	       16 bit expansion memory has a priority of 0.  The higher the
	       priority, the closer to the head of the memory list it will
	       be placed.
	base - the base of the new memory area
	name - the name that will be used in the memory header, or @{"NULL" Link "rexxsupport/NULL"}
	       if no name is to be provided.  This name is not copied, so it
	       must remain valid for as long as the memory header is in the
	       system.

@{b}   NOTES@{ub}
	*DO NOT* add memory to the system with the attribute of MEMF_KICK.
	EXEC will mark your memory as such if it is of the right type.

@{b}   SEE ALSO@{ub}
	@{"AllocMem" Link "exec/AllocMem()"}, @{"exec/memory.h" Link "INCLUDE:exec/memory.h/Main" 0}

@EndNode

@Node "AddPort()" "exec.library/AddPort"

@{b}   NAME@{ub}
	AddPort -- add a public message port to the system

@{b}   SYNOPSIS@{ub}
	AddPort(port)
		A1

	void AddPort(struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} *);

@{b}   FUNCTION@{ub}
	This function attaches a message port structure to the system's
	public message port list, where it can be found by the @{"FindPort()" Link "FindPort()"}
	function.  The name and priority fields of the port structure must
	be initialized prior to calling this function.	If the user does
	not require the priority field, it should be initialized to zero.

	Only ports that will be searched for with @{"FindPort()" Link "FindPort()"} need to
	be added to the system list.  In addition, adding ports is often
	useful during debugging.  If the port will be searched for,
	the priority field should be at least 1 (to avoid the large number
	of inactive ports at priority zero).  If the port will be searched
	for often, set the priority in the 50-100 range (so it will be
	before other less used ports).

	Once a port has been added to the naming list, you must be careful
	to remove the port from the list (via RemPort) before deallocating
	its memory.

@{b}   NOTE@{ub}
	A point of confusion is that clearing a @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} structure to all
	zeros is not enough to prepare it for use.  As mentioned in the
	Exec chapter of the ROM Kernel Manual, the @{"List" Link "INCLUDE:exec/lists.h/Main" 19} for the @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26}
	must be initialized.  This is automatically handled by AddPort(),
	and @{"amiga.lib/CreatePort" Link "amiga_lib/CreatePort()"}.  This initialization can be done manually
	with @{"amiga.lib/NewList" Link "amiga_lib/NewList()"} or the assembly NEWLIST macro.

	Do not AddPort an active port.

@{b}   INPUTS@{ub}
	port - pointer to a message port

@{b}   SEE ALSO@{ub}
	@{"RemPort" Link "exec/RemPort()"}, @{"FindPort" Link "exec/FindPort()"}, @{"amiga.lib/CreatePort" Link "amiga_lib/CreatePort()"}, @{"amiga.lib/NewList" Link "amiga_lib/NewList()"}

@EndNode

@Node "AddResource()" "exec.library/AddResource"

@{b}   NAME@{ub}
	AddResource -- add a resource to the system

@{b}   SYNOPSIS@{ub}
	AddResource(resource)
		    A1

	void AddResource(APTR);

@{b}   FUNCTION@{ub}
	This function adds a new resource to the system and makes it
	available to other users.  The resource must be ready to be called
	at this time.

	Resources currently have no system-imposed structure, however they
	must start with a standard named node (LN_SIZE), and should with
	a standard @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} node (LIB_SIZE).

@{b}   INPUTS@{ub}
	resource - pointer an initialized resource node

@{b}   SEE ALSO@{ub}
	@{"RemResource" Link "exec/RemResource()"}, @{"OpenResource" Link "exec/OpenResource()"}, @{"MakeLibrary" Link "exec/MakeLibrary()"}

@EndNode

@Node "AddSemaphore()" "exec.library/AddSemaphore"

@{b}   NAME@{ub}
	AddSemaphore -- initialize then add a signal semaphore to the system

@{b}   SYNOPSIS@{ub}
	AddSemaphore(signalSemaphore)
		     A1

	void AddSemaphore(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *);

@{b}   FUNCTION@{ub}
	This function attaches a signal semaphore structure to the system's
	public signal semaphore list.  The name and priority fields of the
	semaphore structure must be initialized prior to calling this
	function.  If you do not want to let others rendezvous with this
	semaphore, use @{"InitSemaphore()" Link "InitSemaphore()"} instead.

	If a semaphore has been added to the naming list, you must be
	careful to remove the semaphore from the list (via RemSemaphore)
	before deallocating its memory.

	Semaphores that are linked together in an allocation list (which
	@{"ObtainSemaphoreList()" Link "ObtainSemaphoreList()"} would use) may not be added to the system
	naming list, because the facilities use the link field of the
	signal semaphore in incompatible ways

@{b}   INPUTS@{ub}
       signalSemaphore -- an signal semaphore structure

@{b}   BUGS@{ub}
	Does not work in Exec <V36.  Instead use this code:

	    #include @{"<exec/execbase.h>" Link "INCLUDE:exec/execbase.h/Main" 0}
	    #include @{"<exec/nodes.h>" Link "INCLUDE:exec/nodes.h/Main" 0}
	    extern struct @{"ExecBase" Link "INCLUDE:exec/execbase.h/Main" 32} *SysBase;
		...
	    void LocalAddSemaphore(s)
	    struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *s;
	    {
		s->ss_Link.ln_Type=NT_SIGNALSEM;
		InitSemaphore(s);
		Forbid();
		Enqueue(&SysBase->SemaphoreList,s);
		Permit();
	    }

@{b}   SEE ALSO@{ub}
	@{"RemSemaphore" Link "exec/RemSemaphore()"}, @{"FindSemaphore" Link "exec/FindSemaphore()"}, @{"InitSemaphore" Link "exec/InitSemaphore()"}

@EndNode

@Node "AddTail()" "exec.library/AddTail"

@{b}   NAME@{ub}
	AddTail -- append node to tail of a list

@{b}   SYNOPSIS@{ub}
	AddTail(list, node)
                A0    A1

	void AddTail(struct @{"List" Link "INCLUDE:exec/lists.h/Main" 19} *, struct @{"Node" Link "INCLUDE:exec/nodes.h/Main" 21} *);

@{b}   FUNCTION@{ub}
	Add a node to the tail of a doubly linked list.  Assembly
	programmers may prefer to use the ADDTAIL macro from
	"exec/lists.i".

@{b}   WARNING@{ub}
	This function does not arbitrate for access to the list.  The
	calling task must be the owner of the involved list.

@{b}   INPUTS@{ub}
	list - a pointer to the target list header
	node - a pointer to the node to insert at tail of the list

@{b}   SEE ALSO@{ub}
	@{"AddHead" Link "exec/AddHead()"}, @{"Enqueue" Link "exec/Enqueue()"}, @{"Insert" Link "exec/Insert()"}, @{"Remove" Link "exec/Remove()"}, @{"RemHead" Link "exec/RemHead()"}, @{"RemTail" Link "exec/RemTail()"}

@EndNode

@Node "AddTask()" "exec.library/AddTask"

@{b}   NAME@{ub}
	AddTask -- add a task to the system

@{b}   SYNOPSIS@{ub}
	AddTask(task, initialPC, finalPC)
		A1    A2	 A3

	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75} AddTask(struct @{"Task" Link "INCLUDE:exec/tasks.h/Main" 23} *, @{"APTR" Link "INCLUDE:exec/types.h/Main" 75}, APTR);

@{b}   FUNCTION@{ub}
	Add a task to the system.  A reschedule will be run; the task with
	the highest priority in the system will start to execute (this may
	or may not be the new task).

	Certain fields of the task control block must be initialized and a
	stack allocated prior to calling this function.  The absolute
	smallest stack that is allowable is something in the range of 100
	bytes, but in general the stack size is dependent on what
	subsystems are called. In general 256 bytes is sufficient if only
	Exec is called, and 4K will do if anything in the system is called.
	DO NOT UNDERESTIMATE.  If you use a stack sniffing utility,
	leave a healthy pad above the minimum value.  The system guarantees
	that its stack operations will leave the stack longword aligned.

	This function will temporarily use space from the new task's stack
	for the task's initial set of registers.  This space is allocated
	starting at the SPREG location specified in the task control block
	(not from SPUPPER).  This means that a task's stack may contain
	static data put there prior to its execution.  This is useful for
	providing initialized global variables or some tasks may want to
	use this space for passing the task its initial arguments.

	A task's initial registers are set to zero (except the PC).

	The TC_MEMENTRY field of the task structure may be extended by
	the user to hold additional MemLists (as returned by @{"AllocEntry()" Link "AllocEntry()"}).
	These will be automatically be deallocated at @{"RemTask()" Link "RemTask()"} time.
	If the code you have used to start the task has already added
	something to the MEMENTRY list, simply use @{"AddHead" Link "exec/AddHead()"} to add your
	new MemLists in.  If no initialization has been done, a @{"NewList" Link "amiga_lib/NewList()"} will
	need to be performed.

@{b}   INPUTS@{ub}
	task  - pointer to the task control block (TCB).  All unset fields
		must be zero.
	initialPC - the initial entry point's address
	finalPC - the finalization code entry point's address.  If zero,
		  the system will use a general finalizer. This pointer is
		  placed on the stack as if it were the outermost return
		  address.

@{b}   RESULTS@{ub}
	For V36, AddTask returns either a @{"NULL" Link "rexxsupport/NULL"} or the address of the new
	task.  Old code need not check this.

@{b}   WARNING@{ub}
	Tasks are a low-level building block, and are unable to call
	dos.library, or any system function that might call dos.library.
	See the AmigaDOS @{"CreateProc()" Link "dos/CreateProc()"} for information on Processes.

@{b}   SEE ALSO@{ub}
	@{"RemTask" Link "exec/RemTask()"}, @{"FindTask" Link "exec/FindTask()"}, @{"amiga.lib/CreateTask" Link "amiga_lib/CreateTask()"}, @{"dos/CreateProc" Link "dos/CreateProc()"},
	@{"amiga.lib/NewList" Link "amiga_lib/NewList()"}

@EndNode

@Node "Alert()" "exec.library/Alert"

@{b}   NAME@{ub}
	Alert -- alert the user of an error

@{b}   SYNOPSIS@{ub}
	Alert(alertNum)
	      D7

	void Alert(ULONG);

@{b}   FUNCTION@{ub}
	Alerts the user of a serious system problem.  This function will
	bring the system to a grinding halt, and do whatever is necessary
	to present the user with a message stating what happened.
	Interrupts are disabled, and an attempt to post the alert is made.
	If that fails, the system is reset.  When the system comes up
	again, Exec notices the cause of the failure and tries again to
	post the alert.

	If the Alert is a recoverable type, this call MAY return.

	This call may be made at any time, including interrupts.
	(Well, only in interrupts if it is non-recoverable)

	New, for V39:
	The alert now times out based on the value in LastAlert[3]
	This value is transfered accross warm-reboots and thus will let
	you set it once.  The value is the number of frames that need to
	be displayed before the alert is auto-answered.  A value of
	0 will thus make the alert never be displayed.  Note that
	it is recommended that applications *NOT* change the value in
	LastAlert[] since the main reason for this is to make
	unattended operation of the Amiga (in production enviroments)
	possible.

@{b}   POST-MORTEM DIAGNOSIS@{ub}
	There are several options for determining the cause of a crash.
	Descriptions of each alert number can be found in the "alerts.h"
	include file.

	A remote terminal can be attached to the Amiga's first built-in
	serial port.  Set the communication parameters to 9600 baud, 8 bits,
	no parity.  Before resetting the machine, the Alert function will
	blink the power LED 10 times.  While the power indicator is flashing,
	pressing @{"DELETE" Link "rexxsupport/DELETE"} on the remote terminal will invoke the ROM debugger.

@{b}   INPUT@{ub}
	alertNum   - a number indicating the particular alert.  -1 is
	             not a valid input.

@{b}   NOTE@{ub}
	Much more needs to be said about this function and its implications.

@{b}   SEE ALSO@{ub}
	@{"exec/alerts.h" Link "INCLUDE:exec/alerts.h/Main" 0}

@EndNode

@Node "AllocAbs()" "exec.library/AllocAbs"

@{b}   NAME@{ub}
	AllocAbs -- allocate at a given location

@{b}   SYNOPSIS@{ub}
	memoryBlock = AllocAbs(byteSize, location)
	D0		       D0	 A1

	void *AllocAbs(ULONG, APTR);

@{b}   FUNCTION@{ub}
	This function attempts to allocate memory at a given absolute
	memory location.  Often this is used by boot-surviving entities
	such as recoverable ram-disks.	If the memory is already being
	used, or if there is not enough memory to satisfy the request,
	AllocAbs will return @{"NULL" Link "rexxsupport/NULL"}.

	This block may not be exactly the same as the requested block
	because of rounding, but if the return value is non-zero, the block
	is guaranteed to contain the requested range.

@{b}   INPUTS@{ub}
	byteSize - the size of the desired block in bytes
		   This number is rounded up to the next larger
		   block size for the actual allocation.
	location - the address where the memory MUST be.


@{b}   RESULT@{ub}
	memoryBlock - a pointer to the newly allocated memory block, or
		      @{"NULL" Link "rexxsupport/NULL"} if failed.

@{b}   NOTE@{ub}
	If the free list is corrupt, the system will panic with alert
	AN_MemCorrupt, $01000005.

	The 8 bytes past the end of an AllocAbs will be changed by Exec
	relinking the next block of memory.  Generally you can't trust
	the first 8 bytes of anything you AllocAbs.

@{b}   SEE ALSO@{ub}
	@{"AllocMem" Link "exec/AllocMem()"}, @{"FreeMem" Link "exec/FreeMem()"}

@EndNode

@Node "Allocate()" "exec.library/Allocate"

@{b}   NAME@{ub}
	Allocate - allocate a block of memory

@{b}   SYNOPSIS@{ub}
	memoryBlock=Allocate(memHeader, byteSize)
	D0		     A0 	D0

	void *Allocate(struct @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26} *, ULONG);

@{b}   FUNCTION@{ub}
	This function is used to allocate blocks of memory from a given
	private free memory pool (as specified by a @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26} and its
	memory chunk list).  Allocate will return the first free block that
	is greater than or equal to the requested size.

	All blocks, whether free or allocated, will be block aligned;
	hence, all allocation sizes are rounded up to the next block even
	value (e.g. the minimum allocation resolution is currently 8
	bytes.  A request for 8 bytes will use up exactly 8 bytes.  A
	request for 7 bytes will also use up exactly 8 bytes.).

	This function can be used to manage an application's internal data
	memory.  Note that no arbitration of the @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26} and associated
	free chunk list is done.  You must be the owner before calling
	Allocate.

@{b}   INPUTS@{ub}
	memHeader - points to the local memory list header.
	byteSize - the size of the desired block in bytes.

@{b}   RESULT@{ub}
	memoryBlock - a pointer to the just allocated free block.
	       If there are no free regions large enough to satisfy the
	       request, return zero.

@{b}   EXAMPLE@{ub}
	#include @{"<exec/types.h>" Link "INCLUDE:exec/types.h/Main" 0}
	#include @{"<exec/memory.h>" Link "INCLUDE:exec/memory.h/Main" 0}
	void *AllocMem();
	#define BLOCKSIZE 4096L /* Or whatever you want */

	void main()
	{
	struct @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26} *mh;
	struct @{"MemChunk" Link "INCLUDE:exec/memory.h/Main" 18}  *mc;
	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75}   block1;
	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75}   block2;

	    /* Get the @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26} needed to keep track of our new block */
	    mh = (struct @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26} *)
		 AllocMem((long)sizeof(struct MemHeader), MEMF_CLEAR );
	    if( !mh )
		exit(10);

	    /* Get the actual block the above @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26} will manage */
	    mc = (struct @{"MemChunk" Link "INCLUDE:exec/memory.h/Main" 18} *)AllocMem( BLOCKSIZE, 0L );
	    if( !mc )
		{
		FreeMem( mh, (long)sizeof(struct MemHeader) ); exit(10);
		}

	    mh->mh_Node.ln_Type = NT_MEMORY;
	    mh->mh_Node.ln_Name = "myname";
	    mh->mh_First = mc;
	    mh->mh_Lower = (APTR) mc;
	    mh->mh_Upper = (APTR) ( BLOCKSIZE + (ULONG) mc );
	    mh->mh_Free  = BLOCKSIZE;

	    /* Set up first chunk in the freelist */
	    mc->mc_Next  = NULL;
	    mc->mc_Bytes = BLOCKSIZE;

	    block1 = (APTR) Allocate( mh, 20L );
	    block2 = (APTR) Allocate( mh, 314L );
	    printf("mh=$%lx mc=$%lx\n",mh,mc);
	    printf("Block1=$%lx, Block2=$%lx\n",block1,block2);

	    FreeMem( mh, (long)sizeof(struct MemHeader) );
	    FreeMem( mc, BLOCKSIZE );
	}

@{b}   NOTE@{ub}
	If the free list is corrupt, the system will panic with alert
	AN_MemCorrupt, $01000005.

@{b}   SEE ALSO@{ub}
	@{"Deallocate" Link "exec/Deallocate()"}, @{"exec/memory.h" Link "INCLUDE:exec/memory.h/Main" 0}

@EndNode

@Node "AllocEntry()" "exec.library/AllocEntry"

@{b}   NAME@{ub}
	AllocEntry -- allocate many regions of memory

@{b}   SYNOPSIS@{ub}
	memList = AllocEntry(memList)
	D0		     A0

	struct @{"MemList" Link "INCLUDE:exec/memory.h/Main" 54} *AllocEntry(struct @{"MemList" Link "INCLUDE:exec/memory.h/Main" 54} *);

@{b}   FUNCTION@{ub}
	This function takes a memList structure and allocates enough memory
	to hold the required memory as well as a @{"MemList" Link "INCLUDE:exec/memory.h/Main" 54} structure to keep
	track of it.

	These @{"MemList" Link "INCLUDE:exec/memory.h/Main" 54} structures may be linked together in a task control
	block to keep track of the total memory usage of this task. (See
	the description of TC_MEMENTRY under RemTask).

@{b}   INPUTS@{ub}
	memList -- A @{"MemList" Link "INCLUDE:exec/memory.h/Main" 54} structure filled in with @{"MemEntry" Link "INCLUDE:exec/memory.h/Main" 38} structures.

@{b}   RESULTS@{ub}
	memList -- A different @{"MemList" Link "INCLUDE:exec/memory.h/Main" 54} filled in with the actual memory
	    allocated in the me_Addr field, and their sizes in me_Length.
	    If enough memory cannot be obtained, then the requirements of
	    the allocation that failed is returned and bit 31 is set.

	    WARNING: The result is unusual!  Bit 31 indicates failure.

@{b}   EXAMPLES@{ub}
	The user wants five regions of 2, 4, 8, 16, and 32 bytes in size
	with requirements of MEMF_CLEAR, MEMF_PUBLIC, MEMF_CHIP!MEMF_CLEAR,
	MEMF_CLEAR, and MEMF_PUBLIC!MEMF_CLEAR respectively.  The
	following code fragment would do that:

	    MemListDecl:
		DS.B	LN_SIZE 	    * reserve space for list node
		DC.W	5		    * number of entries
		DC.L	MEMF_CLEAR		    * entry #0
		DC.L	2
		DC.L	MEMF_PUBLIC		    * entry #1
		DC.L	4
		DC.L	MEMF_CHIP!MEMF_CLEAR	    * entry #2
		DC.L	8
		DC.L	MEMF_CLEAR	   	    * entry #3
		DC.L	16
		DC.L	MEMF_PUBLIC!MEMF_CLEAR	    * entry #4
		DC.L	32

	    start:
		LEA.L	MemListDecl(PC),A0
		JSR	_LVOAllocEntry(a6)
		BCLR.L	#31,D0
		BEQ.S	success

		------- Type of memory that we failed on is in D0

@{b}   BUGS@{ub}
	If any one of the allocations fails, this function fails to back
	out fully.  This is fixed by the "SetPatch" program on V1.3
	Workbench disks.

@{b}   SEE ALSO@{ub}
	@{"exec/memory.h" Link "INCLUDE:exec/memory.h/Main" 0}

@EndNode

@Node "AllocMem()" "exec.library/AllocMem"

@{b}   NAME@{ub}
	AllocMem -- allocate memory given certain requirements

@{b}   SYNOPSIS@{ub}
	memoryBlock = AllocMem(byteSize, attributes)
	D0		       D0	 D1

	void *AllocMem(ULONG, ULONG);

@{b}   FUNCTION@{ub}
	This is the memory allocator to be used by system code and
	applications.  It provides a means of specifying that the allocation
	should be made in a memory area accessible to the chips, or
	accessible to shared system code.

	Memory is allocated based on requirements and options.	Any
	"requirement" must be met by a memory allocation, any "option" will
	be applied to the block regardless.  AllocMem will try all memory
	spaces until one is found with the proper requirements and room for
	the memory request.

@{b}   INPUTS@{ub}
	byteSize - the size of the desired block in bytes.  (The operating
		system will automatically round this number to a multiple of
		the system memory chunk size)

	attributes -
	    requirements

		If no flags are set, the system will return the best
		available memory block.  For expanded systems, the fast
		memory pool is searched first.

		MEMF_CHIP:	If the requested memory will be used by
				the Amiga custom chips, this flag *must*
				be set.

				Only certain parts of memory are reachable
				by the special chip sets' DMA circuitry.
				Chip DMA includes screen memory, images that
				are blitted, audio data, copper lists, sprites
				and Pre-V36 trackdisk.device buffers.


		MEMF_FAST:	This is non-chip memory.  If no flag is set
				MEMF_FAST is taken as the default.

				DO NOT SPECIFY MEMF_FAST unless you know
				exactly what you are doing!  If MEMF_FAST is
				set, AllocMem() will fail on machines that
				only have chip memory!  This flag may not
				be set when MEMF_CHIP is set.


		MEMF_PUBLIC:	Memory that must not be mapped, swapped,
				or otherwise made non-addressable. ALL
				MEMORY THAT IS REFERENCED VIA INTERRUPTS
				AND/OR BY OTHER TASKS MUST BE EITHER PUBLIC
				OR LOCKED INTO MEMORY! This includes both
				code and data.


		MEMF_LOCAL:	This is memory that will not go away
				after the CPU RESET instruction.  Normally,
				autoconfig memory boards become unavailable
				after RESET while motherboard memory
				may still be available.  This memory type
				is now automatically set in V36.  Pre-V36
				systems may not have this memory type
				and AllocMem() will then fail.


		MEMF_24BITDMA:	This is memory that is within the address
				range of 24-bit DMA devices.  (Zorro-II)
				This is required if you run a Zorro-II
				DMA device on a machine that has memory
				beyond the 24-bit addressing limit of
				Zorro-II.  This memory type
				is now automatically set in V36.  Pre-V36
				systems may not have this memory type
				and AllocMem() will then fail.


		MEMF_KICK:	This memory is memory that EXEC was able
				to access during/before the KickMem and
				KickTags are processed.  This means that
				if you wish to use these, you should allocate
				memory with this flag.  This flag is
				automaticly set by EXEC in V39.  Pre-V39
				systems may not have this memory type and
				AllocMem() will then fail.  Also, *DO NOT*
				ever add memory the system with this flag
				set.  EXEC will set the flag as needed
				if the memory matches the needs of EXEC.


	    options

		MEMF_CLEAR:	The memory will be initialized to all
				zeros.


		MEMF_REVERSE:	This allocates memory from the top of
				the memory pool.  It searches the pools
				in the same order, such that FAST memory
				will be found first.  However, the
				memory will be allocated from the highest
				address available in the pool.  This
				option is new as of V36.  Note that this
				option has a bug in pre-V39 systems.


		MEMF_NO_EXPUNGE	This will prevent an expunge to happen on
				a failed memory allocation.  This option is
				new to V39 and will be ignored in V37.
				If a memory allocation with this flag
				set fails, the allocator will not cause
				any expunge operations.  (See @{"AddMemHandler()" Link "AddMemHandler()"})


@{b}   RESULT@{ub}
	memoryBlock - a pointer to the newly allocated memory block.
		If there are no free memory regions large enough to satisfy
		the request, zero will be returned.  The pointer must be
		checked for zero before the memory block may be used!
		The memory block returned is long word aligned.

@{b}   WARNING@{ub}
	The result of any memory allocation MUST be checked, and a viable
	error handling path taken.  ANY allocation may fail if memory has
	been filled.

@{b}   EXAMPLES@{ub}
	AllocMem(64,0L)		- @{"Allocate" Link "exec/Allocate()"} the best available memory
	AllocMem(25,MEMF_CLEAR) - @{"Allocate" Link "exec/Allocate()"} the best available memory, and
				  clear it before returning.
	AllocMem(128,MEMF_CHIP) - @{"Allocate" Link "exec/Allocate()"} chip memory
	AllocMem(128,MEMF_CHIP|MEMF_CLEAR) - @{"Allocate" Link "exec/Allocate()"} cleared chip memory
	AllocMem(821,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR) - @{"Allocate" Link "exec/Allocate()"} cleared,
		public, chip memory.

@{b}   NOTE@{ub}
	If the free list is corrupt, the system will panic with alert
	AN_MemCorrupt, $01000005.

	This function may not be called from interrupts.

	A DOS process will have its pr_Result2 field set to
	ERROR_NO_FREE_STORE if the memory allocation fails.

@{b}   SEE ALSO@{ub}
	@{"FreeMem" Link "exec/FreeMem()"}

@EndNode

@Node "AllocPooled()" "exec.library/AllocPooled"

@{b}    NAME@{ub}
	AllocPooled -- @{"Allocate" Link "exec/Allocate()"} memory with the pool manager (V39)

@{b}    SYNOPSIS@{ub}
	memory=AllocPooled(poolHeader,memSize)
	d0                 a0         d0

	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75} AllocPooled(APTR,ULONG);

@{b}    FUNCTION@{ub}
	@{"Allocate" Link "exec/Allocate()"} memSize bytes of memory, and return a pointer. @{"NULL" Link "rexxsupport/NULL"} is
	returned if the allocation fails.

	Doing a @{"DeletePool()" Link "DeletePool()"} on the pool will free all of the puddles
	and thus all of the allocations done with AllocPooled() in that
	pool.  (No need to @{"FreePooled()" Link "FreePooled()"} each allocation)

@{b}    INPUTS@{ub}
	poolHeader - a specific private pool header.
	memSize - the number of bytes to allocate

@{b}    RESULT@{ub}
	A pointer to the memory, or @{"NULL" Link "rexxsupport/NULL"}.
	The memory block returned is long word aligned.

@{b}    NOTES@{ub}
	The pool functions do not protect an individual pool from
	multiple accesses.  The reason is that in most cases the pools
	will be used by a single task.  If your pool is going to
	be used by more than one task you must Semaphore protect
	the pool from having more than one task trying to allocate
	within the same pool at the same time.  Warning:  @{"Forbid()" Link "Forbid()"}
	protection *will not work* in the future.  *Do NOT* assume
	that we will be able to make it work in the future.  AllocPooled()
	may well break a @{"Forbid()" Link "Forbid()"} and as such can only be protected
	by a semaphore.

	To track sizes yourself, the following code can be used:
	Assumes a6=ExecBase

	;
	; Function to do AllocVecPooled(Pool,memSize)
	;
	AllocVecPooled:	addq.l	#4,d0		; Get space for tracking
			move.l	d0,-(sp)	; Save the size
			jsr	_LVOAllocPooled(a6)	; Call pool...
			move.l	(sp)+,d1	; Get size back...
			tst.l	d0		; Check for error
			beq.s	avp_fail	; If @{"NULL" Link "rexxsupport/NULL"}, failed!
			move.l	d0,a0		; Get pointer...
			move.l	d1,(a0)+	; Store size
			move.l	a0,d0		; Get result
	avp_fail:	rts			; return

	;
	; Function to do FreeVecPooled(pool,memory)
	;
	FreeVecPooled:	move.l	-(a1),d0	; Get size / ajust pointer
			jmp	_LVOFreePooled(a6)

@{b}    BUGS@{ub}
	Allocations should not exceed 4294967288 (0xFFFFFFF8) bytes because
	this may trigger a side-effect leading to far less memory to be
	allocated.

@{b}    SEE ALSO@{ub}
	@{"FreePooled()" Link "FreePooled()"}, @{"CreatePool()" Link "CreatePool()"}, @{"DeletePool()" Link "DeletePool()"}

@EndNode

@Node "AllocSignal()" "exec.library/AllocSignal"

@{b}   NAME@{ub}
	AllocSignal -- allocate a signal bit

@{b}   SYNOPSIS@{ub}
	signalNum = AllocSignal(signalNum)
	D0			D0

	@{"BYTE" Link "INCLUDE:exec/types.h/Main" 118} AllocSignal(BYTE);

@{b}   FUNCTION@{ub}
	@{"Allocate" Link "exec/Allocate()"} a signal bit from the current tasks' pool.  Either a
	particular bit, or the next free bit may be allocated.	The signal
	associated with the bit will be properly initialized (cleared).  At
	least 16 user signals are available per task.  Signals should be
	deallocated before the task exits.

	If the signal is already in use (or no free signals are available)
	a -1 is returned.

	Allocated signals are only valid for use with the task that
	allocated them.


@{b}   WARNING@{ub}
	Signals may not be allocated or freed from exception handling code.

@{b}   INPUTS@{ub}
	signalNum - the desired signal number {of 0..31} or -1 for no
		    preference.

@{b}   RESULTS@{ub}
	signalNum - the signal bit number allocated {0..31}. If no signals
		    are available, this function returns -1.

@{b}   SEE ALSO@{ub}
	@{"FreeSignal" Link "exec/FreeSignal()"}

@EndNode

@Node "AllocTrap()" "exec.library/AllocTrap"

@{b}   NAME@{ub}
	AllocTrap -- allocate a processor trap vector

@{b}   SYNOPSIS@{ub}
	trapNum = AllocTrap(trapNum)
	D0		    D0

	@{"LONG" Link "INCLUDE:exec/types.h/Main" 112} AllocTrap(LONG);

@{b}   FUNCTION@{ub}
	@{"Allocate" Link "exec/Allocate()"} a trap number from the current task's pool.  These trap
	numbers are those associated with the 68000 TRAP type instructions.
	Either a particular number, or the next free number may be
	allocated.

	If the trap is already in use (or no free traps are available) a -1
	is returned.

	This function only affects the currently running task.

	Traps are sent to the trap handler pointed at by tc_TrapCode.
	Unless changed by user code, this points to a standard trap
	handler.  The stack frame of the exception handler will be:

		0(SP) = Exception vector number.  This will be in the
			range of 32 to 47 (corresponding to the
			Trap #1...Trap #15 instructions).
		4(SP) = 68000/68010/68020/68030, etc. exception frame

	tc_TrapData is not used.


@{b}   WARNING@{ub}
	Traps may not be allocated or freed from exception handling code.
	You are not allowed to write to the exception table yourself.  In
	fact, on some machines you will have trouble finding it - the VBR
	register may be used to remap its location.

@{b}   INPUTS@{ub}
	trapNum - the desired trap number {of 0..15} or -1
		  for no preference.

@{b}   RESULTS@{ub}
	trapNum - the trap number allocated {of 0..15}.  If no traps are
		  available, this function returns -1.	Instructions of the
		  form "Trap #trapNum" will be sent to the task's trap
		  handler.

@{b}   SEE ALSO@{ub}
	@{"FreeTrap" Link "exec/FreeTrap()"}

@EndNode

@Node "AllocVec()" "exec.library/AllocVec"

@{b}   NAME@{ub}
	AllocVec -- allocate memory and keep track of the size  (V36)

@{b}   SYNOPSIS@{ub}
	memoryBlock = AllocVec(byteSize, attributes)
	D0		       D0	 D1

	void *AllocVec(ULONG, ULONG);

@{b}   FUNCTION@{ub}
	This function works identically to @{"AllocMem()" Link "AllocMem()"}, but tracks the size
	of the allocation.

	See the @{"AllocMem()" Link "AllocMem()"} documentation for details.

@{b}   WARNING@{ub}
	The result of any memory allocation MUST be checked, and a viable
	error handling path taken.  ANY allocation may fail if memory has
	been filled.

@{b}   SEE ALSO@{ub}
	@{"FreeVec" Link "exec/FreeVec()"}, @{"AllocMem" Link "exec/AllocMem()"}

@EndNode

@Node "AttemptSemaphore()" "exec.library/AttemptSemaphore"

@{b}   NAME@{ub}
	AttemptSemaphore -- try to obtain without blocking

@{b}   SYNOPSIS@{ub}
	success = AttemptSemaphore(signalSemaphore)
	D0			   A0

	@{"LONG" Link "INCLUDE:exec/types.h/Main" 112} AttemptSemaphore(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *);

@{b}   FUNCTION@{ub}
	This call is similar to @{"ObtainSemaphore()" Link "ObtainSemaphore()"}, except that it will not
	block if the semaphore could not be locked.

@{b}   INPUT@{ub}
       signalSemaphore -- an initialized signal semaphore structure

@{b}   RESULT@{ub}
	success -- TRUE if the semaphore was locked, false if some
	    other task already possessed the semaphore.

@{b}    NOTE@{ub}
	This call does NOT preserve registers.

@{b}   SEE ALSO@{ub}
	@{"ObtainSemaphore()" Link "ObtainSemaphore()"} @{"ObtainSemaphoreShared()" Link "ObtainSemaphoreShared()"}, @{"ReleaseSemaphore()" Link "ReleaseSemaphore()"},
	@{"exec/semaphores.h" Link "INCLUDE:exec/semaphores.h/Main" 0}

@EndNode

@Node "AttemptSemaphoreShared()" "exec.library/AttemptSemaphoreShared"

@{b}   NAME@{ub}
	AttemptSemaphoreShared -- try to obtain without blocking       (V37)

@{b}   SYNOPSIS@{ub}
	success = AttemptSemaphoreShared(signalSemaphore)
	D0			         A0

	@{"LONG" Link "INCLUDE:exec/types.h/Main" 112} AttemptSemaphoreShared(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *);

@{b}   FUNCTION@{ub}
	This call is similar to @{"ObtainSemaphoreShared()" Link "ObtainSemaphoreShared()"}, except that it
	will not block if the semaphore could not be locked.

@{b}   INPUT@{ub}
       signalSemaphore -- an initialized signal semaphore structure

@{b}   RESULT@{ub}
	success -- TRUE if the semaphore was granted, false if some
	    other task already possessed the semaphore in exclusive mode.

@{b}   NOTE@{ub}
	This call does NOT preserve registers.

	Starting in V39 this call will grant the semaphore if the
	caller is already the owner of an exclusive lock on the semaphore.
	In pre-V39 systems this would not be the case.  If you need this
	feature you can do the following workaround:

	@{"LONG" Link "INCLUDE:exec/types.h/Main" 112} myAttemptSempahoreShared(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *ss)
	{
	@{"LONG" Link "INCLUDE:exec/types.h/Main" 112} result;

		\* Try for a shared semaphore *\
		if (!(result=AttemptSemaphoreShared(ss)))
		{
			\* Now try for the exclusive one... *\
			result=AttempSemaphore(ss);
		}
		return(result);
	}

@{b}   SEE ALSO@{ub}
	@{"ObtainSemaphore()" Link "ObtainSemaphore()"} @{"ObtainSemaphoreShared()" Link "ObtainSemaphoreShared()"}, @{"ReleaseSemaphore()" Link "ReleaseSemaphore()"},
	@{"exec/semaphores.h" Link "INCLUDE:exec/semaphores.h/Main" 0}

@EndNode

@Node "AvailMem()" "exec.library/AvailMem"

@{b}   NAME@{ub}
	AvailMem -- memory available given certain requirements

@{b}   SYNOPSIS@{ub}
	size = AvailMem(attributes)
	D0		D1

	ULONG AvailMem(ULONG);

@{b}   FUNCTION@{ub}
	This function returns the amount of free memory given certain
	attributes.

	To find out what the largest block of a particular type is, add
	MEMF_LARGEST into the requirements argument.  Returning the largest
	block is a slow operation.

@{b}   WARNING@{ub}
	Due to the effect of multitasking, the value returned may not
	actually be the amount of free memory available at that instant.

@{b}   INPUTS@{ub}
	requirements - a requirements mask as specified in @{"AllocMem" Link "exec/AllocMem()"}.  Any
		       of the @{"AllocMem" Link "exec/AllocMem()"} bits are valid, as is MEMF_LARGEST
		       which returns the size of the largest block matching
		       the requirements.

@{b}   RESULT@{ub}
	size - total free space remaining (or the largest free block).

@{b}   NOTE@{ub}
	For V36 Exec, AvailMem(MEMF_LARGEST) does a consistency check on
	the memory list.  @{"Alert" Link "exec/Alert()"} AN_MemoryInsane will be pulled if any mismatch
	is noted.

@{b}   EXAMPLE@{ub}
	AvailMem(MEMF_CHIP|MEMF_LARGEST);
	/* return size of largest available chip memory chunk */

@{b}   SEE ALSO@{ub}
	@{"exec/memory.h" Link "INCLUDE:exec/memory.h/Main" 0}

@EndNode

@Node "CacheClearE()" "exec.library/CacheClearE"

@{b}   NAME@{ub}
	CacheClearE - Cache clearing with extended control (V37)

@{b}   SYNOPSIS@{ub}
	CacheClearE(address,length,caches)
	            a0      d0     d1

	void CacheClearE(APTR,ULONG,ULONG);

@{b}   FUNCTION@{ub}
	@{"Flush" Link "dos/Flush()"} out the contents of the CPU instruction and/or data caches.
	If dirty data cache lines are present, push them to memory first.

	Motorola CPUs have separate instruction and data caches.  A data
	write does not update the instruction cache.  If an instruction is
	written to memory or modified, the old instruction may still exist
	in the cache.  Before attempting to execute the code, a flush of
	the instruction cache is required.

	For most systems, the data cache is not updated by Direct Memory
	Access (DMA), or if some external factor changes shared memory.

	Caches must be cleared after *any* operation that could cause
	invalid or stale data.  The most common cases are DMA and modifying
	instructions using the processor.

	Some examples:
			Self modifying code
			Building Jump tables
			Run-time code patches
			Relocating code for use at different addresses.
			Loading code from disk

@{b}   INPUTS@{ub}
	address - Address to start the operation.  This may be rounded
		  due to hardware granularity.
	length	- Length of area to be cleared, or $FFFFFFFF to indicate all
		  addresses should be cleared.
	caches  - Bit flags to indicate what caches to affect.  The current
		  supported flags are:
			CACRF_ClearI	;Clear instruction cache
			CACRF_ClearD	;Clear data cache
		  All other bits are reserved for future definition.

@{b}   NOTES@{ub}
	On systems with a copyback mode cache, any dirty data is pushed
	to memory as a part of this operation.

	Regardless of the length given, the function will determine the most
	efficient way to implement the operation.  For some cache systems,
	including the 68030, the overhead partially clearing a cache is often
	too great.  The entire cache may be cleared.

	For all current Amiga models, Chip memory is set with Instruction
	caching enabled, data caching disabled.  This prevents coherency
	conflicts with the blitter or other custom chip DMA.  @{"Custom" Link "INCLUDE:hardware/custom.h/Main" 23} chip
	registers are marked as non-cacheable by the hardware.

	The system takes care of appropriately flushing the caches for normal
	operations.  The instruction cache is cleared by all calls that
	modify instructions, including @{"LoadSeg()" Link "dos/LoadSeg()"}, @{"MakeLibrary()" Link "MakeLibrary()"} and
	@{"SetFunction()" Link "SetFunction()"}.

@{b}   SEE ALSO@{ub}
	exec/execbase.i, @{"CacheControl" Link "exec/CacheControl()"}, @{"CacheClearU" Link "exec/CacheClearU()"}

@EndNode

@Node "CacheClearU()" "exec.library/CacheClearU"

@{b}   NAME@{ub}
	CacheClearU - User callable simple cache clearing (V37)

@{b}   SYNOPSIS@{ub}
	CacheClearU()

	void CacheClearU(void);

@{b}   FUNCTION@{ub}
	@{"Flush" Link "dos/Flush()"} out the contents of any CPU instruction and data caches.
	If dirty data cache lines are present, push them to memory first.

	Caches must be cleared after *any* operation that could cause
	invalid or stale data.  The most common cases are DMA and modifying
	instructions using the processor.  See the @{"CacheClearE()" Link "CacheClearE()"} autodoc
	for a more complete description.

	Some examples of when the cache needs clearing:
			Self modifying code
			Building Jump tables
			Run-time code patches
			Relocating code for use at different addresses.
			Loading code from disk

@{b}   SEE ALSO@{ub}
	exec/execbase.i, @{"CacheControl" Link "exec/CacheControl()"}, @{"CacheClearE" Link "exec/CacheClearE()"}

@EndNode

@Node "CacheControl()" "exec.library/CacheControl"

@{b}   NAME@{ub}
	CacheControl - Instruction & data cache control

@{b}   SYNOPSIS@{ub}
	oldBits = CacheControl(cacheBits,cacheMask)
	D0                     D0        D1

	ULONG CacheControl(ULONG,ULONG);

@{b}   FUNCTION@{ub}
	This function provides global control of any instruction or data
	caches that may be connected to the system.  All settings are
	global -- per task control is not provided.

	The action taken by this function will depend on the type of
	CPU installed.  This function may be patched to support external
	caches, or different cache architectures.  In all cases the function
	will attempt to best emulate the provided settings.  Use of this
	function may save state specific to the caches involved.

	The list of supported settings is provided in the exec/execbase.i
	include file.  The bits currently defined map directly to the Motorola
	68030 CPU CACR register.  Alternate cache solutions may patch into
	the Exec cache functions.  Where possible, bits will be interpreted to
	have the same meaning on the installed cache.

@{b}   INPUTS@{ub}
	cacheBits - new values for the bits specified in cacheMask.

	cacheMask - a mask with ones for all bits to be changed.

@{b}   RESULT@{ub}
	oldBits   - the complete prior values for all settings.

@{b}   NOTE@{ub}
	As a side effect, this function clears all caches.

@{b}   SEE ALSO@{ub}
	exec/execbase.i, @{"CacheClearU" Link "exec/CacheClearU()"}, @{"CacheClearE" Link "exec/CacheClearE()"}

@EndNode

@Node "CachePostDMA()" "exec.library/CachePostDMA"

@{b}   NAME@{ub}
	CachePostDMA - Take actions after to hardware DMA  (V37)

@{b}   SYNOPSIS@{ub}
	CachePostDMA(vaddress,&length,flags)
	             a0       a1      d0

	CachePostDMA(APTR,@{"LONG" Link "INCLUDE:exec/types.h/Main" 112} *,ULONG);

@{b}   FUNCTION@{ub}
	Take all appropriate steps after Direct Memory Access (DMA).  This
	function is primarily intended for writers of DMA device drivers.  The
	action will depend on the CPU type installed, caching modes, and the
	state of any Memory Management @{"Unit" Link "INCLUDE:exec/devices.h/Main" 30} (MMU) activity.

	As implemented
		68000 - Do nothing
		68010 - Do nothing
		68020 - Do nothing
		68030 - @{"Flush" Link "dos/Flush()"} the data cache
		68040 - @{"Flush" Link "dos/Flush()"} matching areas of the data cache
		????? - External cache boards, Virtual Memory Systems, or
			future hardware may patch this vector to best emulate
			the intended behavior.
			With a Bus-Snooping CPU, this function my end up
			doing nothing.

@{b}   INPUTS@{ub}
	address	- Same as initially passed to @{"CachePreDMA" Link "exec/CachePreDMA()"}
	length	- Same as initially passed to @{"CachePreDMA" Link "exec/CachePreDMA()"}
	flags	- Values:
			DMA_NoModify - If the area was not modified (and
			thus there is no reason to flush the cache) set
			this bit.

			DMA_ReadFromRAM - Indicates that this DMA is a
			read from RAM to the DMA device (ie - a write
			to the hard drive)  This flag is not required
			but if used must match in both the PreDMA and
			PostDMA calls.  This flag *should* be used to
			help the system provide the best performance.
			This flag is safe in all versions of CachePostDMA()

@{b}   SEE ALSO@{ub}
	exec/execbase.i, @{"CachePreDMA" Link "exec/CachePreDMA()"}, @{"CacheClearU" Link "exec/CacheClearU()"}, @{"CacheClearE" Link "exec/CacheClearE()"}

@EndNode

@Node "CachePreDMA()" "exec.library/CachePreDMA"

@{b}   NAME@{ub}
	CachePreDMA - Take actions prior to hardware DMA  (V37)

@{b}   SYNOPSIS@{ub}
	paddress = CachePreDMA(vaddress,&length,flags)
	d0                     a0       a1      d0

	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75} CachePreDMA(APTR,@{"LONG" Link "INCLUDE:exec/types.h/Main" 112} *,ULONG);

@{b}   FUNCTION@{ub}
	Take all appropriate steps before Direct Memory Access (DMA).  This
	function is primarily intended for writers of DMA device drivers.  The
	action will depend on the CPU type installed, caching modes, and the
	state of any Memory Management @{"Unit" Link "INCLUDE:exec/devices.h/Main" 30} (MMU) activity.

	This function supports advanced cache architectures that have
	"copyback" modes.  With copyback, write data may be cached, but not
	actually flushed out to memory.  If the CPU has unflushed data at the
	time of DMA, data may be lost.

	As implemented
		68000 - Do nothing
		68010 - Do nothing
		68020 - Do nothing
		68030 - Do nothing
		68040 - @{"Write" Link "dos/Write()"} any matching dirty cache lines back to memory.
			As a side effect of the 68040's design, matching data
			cache lines are also invalidated -- future CPUs may
			be different.
		????? - External cache boards, Virtual Memory Systems, or
			future hardware may patch this vector to best emulate
			the intended behavior.
			With a Bus-Snooping CPU, this function my end up
			doing nothing.

@{b}   INPUTS@{ub}
	address	- Base address to start the action.
	length	- Pointer to a longword with a length.
	flags	- Values:
			DMA_Continue - Indicates this call is to complete
			a prior request that was broken up.

			DMA_ReadFromRAM - Indicates that this DMA is a
			read from RAM to the DMA device (ie - a write
			to the hard drive)  This flag is not required
			but if used must match in both the PreDMA and
			PostDMA calls.  This flag *should* be used to
			help the system provide the best performance.
			This flag is safe in all versions of CachePreDMA()

@{b}   RESULTS@{ub}
	paddress- Physical address that corresponds to the input virtual
		  address.
	&length	- This length value will be updated to reflect the contiguous
		  length of physical memory present at paddress.  This may
		  be smaller than the requested length.  To get the mapping
		  for the next chunk of memory, call the function again with
		  a new address, length, and the DMA_Continue flag.

@{b}   NOTE@{ub}
	Due to processor granularity, areas outside of the address range
	may be affected by the cache flushing actions.  Care has been taken
	to ensure that no harm is done outside the range, and that activities
	on overlapping cache lines won't harm data.

@{b}   SEE ALSO@{ub}
	exec/execbase.i, @{"CachePostDMA" Link "exec/CachePostDMA()"}, @{"CacheClearU" Link "exec/CacheClearU()"}, @{"CacheClearE" Link "exec/CacheClearE()"}

@EndNode

@Node "Cause()" "exec.library/Cause"

@{b}   NAME@{ub}
       Cause -- cause a software interrupt

@{b}   SYNOPSIS@{ub}
       Cause(interrupt)
	     A1

       void Cause(struct @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} *);

@{b}   FUNCTION@{ub}
	This function causes a software interrupt to occur.  If it is
	called from user mode (and processor level 0), the software
	interrupt will preempt the current task.  This call is often used
	by high-level hardware interrupts to defer medium-length processing
	down to a lower interrupt level.  Note that a software interrupt is
	still a real interrupt, and must obey the same restrictions on what
	system function it may call.

	Currently only 5 software interrupt priorities are implemented:
	-32, -16, 0, +16, and +32.  Priorities in between are truncated,
	values outside the -32/+32 range are not allowed.

@{b}   NOTE@{ub}
	When setting up the @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} structure, set the node type to
	NT_INTERRUPT, or NT_UNKOWN.

@{b}   IMPLEMENTATION@{ub}
	1> Checks if the node type is NT_SOFTINT.  If so does nothing since
	   the softint is already pending.  No nest count is maintained.
	2> Sets the node type to NT_SOFTINT.
	3> Links into one of the 5 priority queues.
	4> Pokes the hardware interrupt bit used for softints.

	The node type returns to NT_INTERRUPT after removal from the list.

@{b}   INPUTS@{ub}
	interrupt - pointer to a properly initialized interrupt node

@{b}   BUGS@{ub}
	Unlike other Interrupts, SoftInts must preserve the value of A6.

@EndNode

@Node "CheckIO()" "exec.library/CheckIO"

@{b}   NAME@{ub}
	CheckIO -- get the status of an @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16}

@{b}   SYNOPSIS@{ub}
	result = CheckIO(iORequest)
	D0		 A1

	struct @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} *CheckIO(struct @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} *);

@{b}   FUNCTION@{ub}
	This function determines the current state of an I/O request and
	returns @{"NULL" Link "rexxsupport/NULL"} if the I/O has not yet completed.  This function
	effectively hides the internals of the I/O completion mechanism.

	CheckIO() will NOT remove the returned @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} from the reply port.
	This is best performed with @{"WaitIO()" Link "WaitIO()"}. If the request has already
	completed, @{"WaitIO()" Link "WaitIO()"} will return quickly. Use of the @{"Remove()" Link "Remove()"}
	function is dangerous, since other tasks may still be adding things
	to your message port; a @{"Disable()" Link "Disable()"} would be required.

	This function should NOT be used to busy loop (looping until IO is
	complete).  @{"WaitIO()" Link "WaitIO()"} is provided for that purpose.

@{b}   INPUTS@{ub}
	iORequest - pointer to an I/O request block

@{b}   RESULTS@{ub}
	result - @{"NULL" Link "rexxsupport/NULL"} if I/O is still in progress.  Otherwise
		 D0 points to the @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} block.

@{b}   BUGS@{ub}
	Previously, CheckIO() used to be documented to return a @{"BOOL" Link "INCLUDE:exec/types.h/Main" 168}
	result. This was incorrect.

@{b}   NOTE@{ub}
	CheckIO can hang if called on an @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} that has never been used.
	This occurs if io_Message.mn_Node.ln_Type of the @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} is set to
	"NT_MESSAGE". Instead simply set LN_TYPE to 0.

@{b}   SEE ALSO@{ub}
	@{"DoIO" Link "exec/DoIO()"}, @{"SendIO" Link "exec/SendIO()"}, @{"WaitIO" Link "exec/WaitIO()"}, @{"AbortIO" Link "timer/AbortIO()"}

@EndNode

@Node "CloseDevice()" "exec.library/CloseDevice"

@{b}   NAME@{ub}
	CloseDevice -- conclude access to a device

@{b}   SYNOPSIS@{ub}
	CloseDevice(iORequest)
		    A1

	void CloseDevice(struct @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} *);

@{b}   FUNCTION@{ub}
	This function informs the device that access to a device/unit
	previously opened has been concluded.  The device may perform
	certain house-cleaning operations.

	The user must ensure that all outstanding IORequests have been
	returned before closing the device.  The @{"AbortIO" Link "timer/AbortIO()"} function can kill
	any stragglers.

	After a close, the I/O request structure is free to be reused.
	Starting with V36 exec it is safe to CloseDevice() with an
	@{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} that is either cleared to zeros, or failed to
	open.

@{b}   INPUTS@{ub}
	iORequest - pointer to an I/O request structure

@{b}   SEE ALSO@{ub}
	@{"OpenDevice" Link "trackdisk/OpenDevice()"}

@EndNode

@Node "CloseLibrary()" "exec.library/CloseLibrary"

@{b}   NAME@{ub}
	CloseLibrary -- conclude access to a library

@{b}   SYNOPSIS@{ub}
	CloseLibrary(library)
		     A1

	void CloseLibrary(struct @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} *);

@{b}   FUNCTION@{ub}
	This function informs the system that access to the given library
	has been concluded.  The user must not reference the library or any
	function in the library after this close.

	Starting with V36, it is safe to pass a @{"NULL" Link "rexxsupport/NULL"} instead of
	a library pointer.

@{b}   INPUTS@{ub}
	library - pointer to a library node

@{b}   NOTE@{ub}
	@{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} writers must pass a SegList pointer or @{"NULL" Link "rexxsupport/NULL"} back from their
	open point.  This value is used by the system, and not visible as
	a return code from CloseLibrary.

@{b}   SEE ALSO@{ub}
	@{"OpenLibrary" Link "exec/OpenLibrary()"}

@EndNode

@Node "ColdReboot()" "exec.library/ColdReboot"

@{b}    NAME@{ub}
	ColdReboot - reboot the Amiga (V36)

@{b}    SYNOPSIS@{ub}
	ColdReboot()

	void ColdReboot(void);

@{b}    FUNCTION@{ub}
	Reboot the machine.  All external memory and periperals will be
	RESET, and the machine will start its power up diagnostics.

	This function never returns.

@{b}    INPUT@{ub}
	A chaotic pile of disoriented bits.

@{b}    RESULTS@{ub}
	An altogether totally integrated living system.

@EndNode

@Node "CopyMem()" "exec.library/CopyMem"

@{b}   NAME@{ub}
	CopyMem - general purpose memory copy function

@{b}   SYNOPSIS@{ub}
	CopyMem( source, dest, size )
		 A0	 A1    D0

	void CopyMem(APTR,@{"APTR" Link "INCLUDE:exec/types.h/Main" 75},ULONG);

@{b}   FUNCTION@{ub}
	CopyMem is a general purpose, fast memory copy function.  It can
	deal with arbitrary lengths, with its pointers on arbitrary
	alignments.  It attempts to optimize larger copies with more
	efficient copies, it uses byte copies for small moves, parts of
	larger copies, or the entire copy if the source and destination are
	misaligned with respect to each other.

	The internal implementation of this function will change from
	system to system, and may be implemented via hardware DMA.

@{b}   CAUTION@{ub}
	Arbitrary overlapping copies are not supported.

@{b}   INPUTS@{ub}
	source - a pointer to the source data region
	dest  - a pointer to the destination data region
	size  - the size (in bytes) of the memory area.  Zero copies
		zero bytes

@{b}   SEE ALSO@{ub}
	@{"CopyMemQuick" Link "exec/CopyMemQuick()"}

@EndNode

@Node "CopyMemQuick()" "exec.library/CopyMemQuick"

@{b}   NAME@{ub}
	CopyMemQuick - optimized memory copy function

@{b}   SYNOPSIS@{ub}
	CopyMemQuick( source, dest, size )
		      A0      A1    D0

	void CopyMemQuick(ULONG *,ULONG *,ULONG);

@{b}   FUNCTION@{ub}
	CopyMemQuick is a highly optimized memory copy function, with
	restrictions on the size and alignment of its arguments. Both the
	source and destination pointers must be longword aligned.  In
	addition, the size must be an integral number of longwords (e.g.
	the size must be evenly divisible by four).

	The internal implementation of this function will change from system
	to system, and may be implemented via hardware DMA.

@{b}   CAUTION@{ub}
	Arbitrary overlapping copies are not supported.

@{b}   INPUTS@{ub}
	source - a pointer to the source data region, long aligned
	dest -  a pointer to the destination data region, long aligned
	size -  the size (in bytes) of the memory area.  Zero copies
		zero bytes.

@{b}   SEE ALSO@{ub}
	@{"CopyMem" Link "exec/CopyMem()"}

@EndNode

@Node "CreateIORequest()" "exec.library/CreateIORequest"

@{b}   NAME@{ub}
	CreateIORequest() -- create an @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} structure  (V36)

@{b}   SYNOPSIS@{ub}
	ioReq = CreateIORequest( ioReplyPort, size );
	                         A0           D0

	struct @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} *CreateIORequest(struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} *, ULONG);

@{b}   FUNCTION@{ub}
	Allocates memory for and initializes a new IO request block
	of a user-specified number of bytes.  The number of bytes
	must be at least as large as a "struct Message".

@{b}   INPUTS@{ub}
	ioReplyPort - Pointer to a port for replies (an initialized message
		port, as created by @{"CreateMsgPort()" Link "CreateMsgPort()"} ).  If @{"NULL" Link "rexxsupport/NULL"}, this
		function fails.
	size - the size of the IO request to be created.

@{b}   RESULT@{ub}
	ioReq - A pointer to the new @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} block, or @{"NULL" Link "rexxsupport/NULL"}.

@{b}   SEE ALSO@{ub}
	@{"DeleteIORequest" Link "exec/DeleteIORequest()"}, @{"CreateMsgPort()" Link "CreateMsgPort()"}, @{"amiga.lib/CreateExtIO()" Link "amiga_lib/CreateExtIO()"}

@EndNode

@Node "CreateMsgPort()" "exec.library/CreateMsgPort"

@{b}   NAME@{ub}
	CreateMsgPort - @{"Allocate" Link "exec/Allocate()"} and initialize a new message port  (V36)

@{b}   SYNOPSIS@{ub}
	CreateMsgPort()

	struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} * CreateMsgPort(void);

@{b}   FUNCTION@{ub}
	Allocates and initializes a new message port.  The message list
	of the new port will be prepared for use (via NewList).  A signal
	bit will be allocated, and the port will be set to signal your
	task when a message arrives (PA_SIGNAL).

	You *must* use @{"DeleteMsgPort()" Link "DeleteMsgPort()"} to delete ports created with
	CreateMsgPort()!

@{b}   RESULT@{ub}
	@{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} - A new @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} structure ready for use, or @{"NULL" Link "rexxsupport/NULL"} if out of
		memory or signals.  If you wish to add this port to the public
		port list, fill in the mp_Node.ln_Name and mp_Node.ln_Pri
		fields, then call @{"AddPort()" Link "AddPort()"}.  Don't forget RemPort()!

@{b}   SEE ALSO@{ub}
	@{"DeleteMsgPort()" Link "DeleteMsgPort()"}, @{"exec/AddPort()" Link "AddPort()"}, @{"exec/ports.h" Link "INCLUDE:exec/ports.h/Main" 0}, @{"amiga.lib/CreatePort()" Link "amiga_lib/CreatePort()"}

@EndNode

@Node "CreatePool()" "exec.library/CreatePool"

@{b}    NAME@{ub}
	CreatePool -- Generate a private memory pool header (V39)

@{b}    SYNOPSIS@{ub}
	newPool=CreatePool(memFlags,puddleSize,threshSize)
	a0                 d0       d1         d2

	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75} CreatePool(ULONG,ULONG,ULONG);

@{b}    FUNCTION@{ub}
	@{"Allocate" Link "exec/Allocate()"} and prepare a new memory pool header.	Each pool is a
	separate tracking system for memory of a specific type.  Any number
	of pools may exist in the system.

	Pools automatically expand and shrink based on demand.	Fixed sized
	"puddles" are allocated by the pool manager when more total memory
	is needed.  Many small allocations can fit in a single puddle.
	Allocations larger than the threshSize are allocation in their own
	puddles.

	At any time individual allocations may be freed.  Or, the entire
	pool may be removed in a single step.

@{b}    INPUTS@{ub}
	memFlags - a memory flags specifier, as taken by @{"AllocMem" Link "exec/AllocMem()"}.
	puddleSize - the size of Puddles...
	threshSize - the largest allocation that goes into normal puddles
	             This *MUST* be less than or equal to puddleSize
	             (CreatePool() will fail if it is not)

@{b}    RESULT@{ub}
	The address of a new pool header, or @{"NULL" Link "rexxsupport/NULL"} for error.

@{b}    NOTES@{ub}
	The memFlags you specify are used by @{"AllocPooled()" Link "AllocPooled()"} only, not
	by CreatePool(). The CreatePool() function will allocate memory
	for its management data structures using MEMF_ANY. For example, if you
	call CreatePool(MEMF_FAST, ...) and expect it to return @{"NULL" Link "rexxsupport/NULL"} if no
	fast memory is available you may find that it succeeds. Subsequent
	@{"AllocPooled()" Link "AllocPooled()"} calls for this pool will, however, fail on a system
	without fast memory.


	The memory pools solve three problems which allocating memory through
	@{"AllocMem()" Link "AllocMem()"}, @{"Allocate()" Link "Allocate()"} and @{"AllocVec()" Link "AllocVec()"} either do not address or which
	are part of how they have to work:

	* Memory pools keep track of the allocations made, so that you may release
	  all of them by calling @{"DeletePool()" Link "DeletePool()"} instead of releasing each single
	  allocation separately.

	* Allocating and releasing memory from a pool does not need to involve
	  the @{"Forbid()/Permit()" Link "Permit()"} locking which is mandatory for @{"AllocMem()" Link "AllocMem()"},
	  @{"FreeMem()" Link "FreeMem()"}, etc. Because of how much effort exec.library spends on
	  finding a fitting memory chunk to allocate from and in turn freeing
	  and coalescing freed memory chunks into larger chunks, you would not
	  want this to happen while multitasking is temporarily disabled.

	* Small allocations made from pools no longer affect the overall
	  fragmentation of the available Amiga memory.

	These features benefit not just your application, it also helps every
	other Amiga software running at the same time.

	These benefits come with costs which you should be aware of when making
	the choice to adopt memory pools for your software.

	* Tracking memory allocations can add a noticeable overhead to those
	  allocations which are smaller than or equal to the threshold size given
	  at CreatePool() time. This overhead exists because each such small
	  allocation has to be found first when you call @{"FreePooled()" Link "FreePooled()"}.
	  The more puddles are in use, the more time it will take to find the
	  puddle which it was allocated from.

	* Only one @{"Task/Process" Link "INCLUDE:dos/dosextens.h/Main" 39} at a time may allocate memory from a pool. This
	  is why @{"AllocMem()" Link "AllocMem()"}, @{"FreeMem()" Link "FreeMem()"}, etc. imply @{"Forbid()/Permit()" Link "Permit()"} locking.
	  If your software is sharing a memory pool among several Tasks/Processes
	  then you will have to use an arbitration mechanism such as a
	  @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} to allow only a single client at a time to access the
	  pool.

	  This is of particular importance because pools optimize the
	  layout of the puddles in response to how frequently allocations and
	  deallocations are made from a pool, which is called "bubbling". The
	  more often a puddle is used, the less time will be spent on finding
	  it when releasing an allocation from it.

	  If no arbitration mechanism is available, you run the risk of corrupting
	  both the pool contents and the memory managed through it.

	  Sharing the same memory pool among several Tasks/Processes can cause the
	  number of puddles to grow over time which are almost empty but never get
	  memory allocated from them. This is a side-effect of how the layout of the
	  puddles is optimized over time. To avoid this problem you should consider
	  breaking down a single shared memory pool into separate pools if your
	  software architecture permits it.

	* While using memory pools will curb overall memory fragmentation, you may
	  find that fragmentation issues affect the puddles more strongly. If
	  allocations vary greatly in size and do not exceed the threshold value
	  given at CreatePool() time you may end up with puddles which are only
	  partly filled, wasting memory. If possible, try to match the puddle size
	  and the threshold size to the allocation sizes you are most likely to use.

@{b}    BUGS@{ub}
	Avoid using a puddle size of 0 bytes. It will have the effect of
	each @{"AllocPooled()" Link "AllocPooled()"} call resulting in a separate memory allocation.
	This defeats the purpose of the memory pools, which is in curbing
	memory fragmentation and the need to block multitasking when memory
	has to be allocated from the global pool.

	Puddle sizes should not exceed 4294967272 (0xFFFFFFE8) bytes because
	this may trigger a side-effect leading to far less memory to be
	allocated.

	Creating a pool with MEMF_CLEAR set in the memFlags parameter has
	a side-effect in slowing down all memory allocations made. The
	creation of a new puddle will result in it getting set to zero,
	and any allocation made from that puddle will set it to zero
	all over again. If you can, avoid using MEMF_CLEAR and set the
	memory allocated by @{"AllocPooled()" Link "AllocPooled()"} to zero all by yourself.


@{b}    SEE ALSO@{ub}
	@{"DeletePool()" Link "DeletePool()"}, @{"AllocPooled()" Link "AllocPooled()"}, @{"FreePooled()" Link "FreePooled()"}, exec/memory.i

@EndNode

@Node "Deallocate()" "exec.library/Deallocate"

@{b}   NAME@{ub}
	Deallocate -- deallocate a block of memory

@{b}   SYNOPSIS@{ub}
	Deallocate(memHeader, memoryBlock, byteSize)
		   A0	      A1	   D0

	void Deallocate(struct @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26} *,@{"APTR" Link "INCLUDE:exec/types.h/Main" 75},ULONG);

@{b}   FUNCTION@{ub}
	This function deallocates memory by returning it to the appropriate
	private free memory pool.  This function can be used to free an
	entire block allocated with the above function, or it can be used
	to free a sub-block of a previously allocated block.  Sub-blocks
	must be an even multiple of the memory chunk size (currently 8
	bytes).

	This function can even be used to add a new free region to an
	existing @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26}, however the extent pointers in the @{"MemHeader" Link "INCLUDE:exec/memory.h/Main" 26}
	will no longer be valid.

	If memoryBlock is not on a block boundary (MEM_BLOCKSIZE) then it
	will be rounded down in a manner compatible with @{"Allocate()" Link "Allocate()"}.  Note
	that this will work correctly with all the memory allocation
	functions, but may cause surprises if one is freeing only part of a
	region.  The size of the block will be rounded up, so the freed
	block will fill to an even memory block boundary.

@{b}   INPUTS@{ub}
	memHeader - points to the memory header this block is part of.
	memoryBlock - address of memory block to free.
	byteSize - the size of the block in bytes. If @{"NULL" Link "rexxsupport/NULL"}, nothing
		   happens.

@{b}   SEE ALSO@{ub}
	@{"Allocate" Link "exec/Allocate()"}, @{"exec/memory.h" Link "INCLUDE:exec/memory.h/Main" 0}

@EndNode

@Node "Debug()" "exec.library/Debug"

@{b}   NAME@{ub}
	Debug -- run the system debugger

@{b}   SYNOPSIS@{ub}
	Debug(flags)
	      D0

	void Debug(ULONG);

@{b}   FUNCTION@{ub}
	This function calls the system debugger.  By default this debugger
	is "SAD" in V39 and V40, and "ROM-WACK" otherwise, including V45 and
	above. Other debuggers are encouraged to take over this entry point
	(via @{"SetFunction()" Link "SetFunction()"}) so that when an application calls Debug(), the
	alternative debugger will get control.  Currently a zero is
	passed to allow future expansion.

@{b}   NOTE@{ub}
	The Debug() call may be made when the system is in a questionable
	state; if you have a @{"SetFunction()" Link "SetFunction()"} patch, make few assumptions, be
	prepared for @{"Supervisor" Link "exec/Supervisor()"} mode, and be aware of differences in the
	Motorola stack frames on the 68000,'10,'20,'30,'40 (etc.)

@{b}   BUGS@{ub}
	In ROMWack, calling this function in SUPERVISOR state would have
	caused the a5 register to be trashed and the user stack pointer to
	be trashed. @{"exec/Alert()" Link "Alert()"} also trashed d7, and the dos.library
	exception hook trashed all other registers. Also, ROMWack could not
	recover in case the VBR of the 68010 or beyond moved.

@{b}   SEE ALSO@{ub}
	@{"SetFunction()" Link "SetFunction()"}
	your favorite debugger's manual...
	the ROM-WACK chapter of the ROM Kernel Manual...

@EndNode

@Node "DeleteIORequest()" "exec.library/DeleteIORequest"

@{b}   NAME@{ub}
	DeleteIORequest() - Free a request made by @{"CreateIORequest()" Link "CreateIORequest()"}  (V36)

@{b}   SYNOPSIS@{ub}
	DeleteIORequest( ioReq );
	                 a0

	void DeleteIORequest(APTR);

@{b}   FUNCTION@{ub}
	Frees up an IO request as allocated by @{"CreateIORequest()" Link "CreateIORequest()"}.

@{b}   INPUTS@{ub}
	ioReq - A pointer to the @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} block to be freed, or @{"NULL" Link "rexxsupport/NULL"}.
		This function uses the io_Message.mn_Length field to
		determine how much memory to free.

@{b}   SEE ALSO@{ub}
	@{"CreateIORequest()" Link "CreateIORequest()"}, @{"amiga.lib/DeleteExtIO()" Link "amiga_lib/DeleteExtIO()"}

@EndNode

@Node "DeleteMsgPort()" "exec.library/DeleteMsgPort"

@{b}   NAME@{ub}
	DeleteMsgPort - Free a message port created by @{"CreateMsgPort" Link "exec/CreateMsgPort()"}  (V36)

@{b}   SYNOPSIS@{ub}
	DeleteMsgPort(msgPort)
		      a0

	void DeleteMsgPort(struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} *);

@{b}   FUNCTION@{ub}
	Frees a message port created by @{"CreateMsgPort()" Link "CreateMsgPort()"}.  All messages that
	may have been attached to this port must have already been
	replied to.

@{b}   INPUTS@{ub}
	msgPort - A message port.  @{"NULL" Link "rexxsupport/NULL"} for no action.

@{b}   SEE ALSO@{ub}
	@{"CreateMsgPort()" Link "CreateMsgPort()"}, @{"amiga.lib/DeletePort()" Link "amiga_lib/DeletePort()"}

@EndNode

@Node "DeletePool()" "exec.library/DeletePool"

@{b}    NAME@{ub}
	DeletePool --  Drain an entire memory pool (V39)

@{b}    SYNOPSIS@{ub}
	DeletePool(poolHeader)
	           a0

	void DeletePool(APTR);

@{b}    FUNCTION@{ub}
	Frees all memory in all pudles of the specified pool header, then
	deletes the pool header.  Individual free calls are not needed.

@{b}    INPUTS@{ub}
	poolHeader - as returned by @{"CreatePool()" Link "CreatePool()"}.

@{b}    SEE ALSO@{ub}
	@{"CreatePool()" Link "CreatePool()"}, @{"AllocPooled()" Link "AllocPooled()"}, @{"FreePooled()" Link "FreePooled()"}

@EndNode

@Node "Disable()" "exec.library/Disable"

@{b}    NAME@{ub}
	Disable -- disable interrupt processing.

@{b}    SYNOPSIS@{ub}
	Disable();

	void Disable(void);

@{b}    FUNCTION@{ub}
	Prevents interrupts from being handled by the system, until a
	matching @{"Enable()" Link "Enable()"} is executed.  Disable() implies @{"Forbid()" Link "Forbid()"}.

	DO NOT USE THIS CALL WITHOUT GOOD JUSTIFICATION.  THIS CALL IS
	VERY DANGEROUS!

@{b}    RESULTS@{ub}
	All interrupt processing is deferred until the task executing makes
	a call to @{"Enable()" Link "Enable()"} or is placed in a wait state.  Normal task
	rescheduling does not occur while interrupts are disabled.  In order
	to restore normal interrupt processing, the programmer must execute
	exactly one call to @{"Enable()" Link "Enable()"} for every call to Disable().

	IMPORTANT REMINDER:

	It is important to remember that there is a danger in using
	disabled sections.  Disabling interrupts for more than ~250
	microseconds will prevent vital system functions (especially serial
	I/0) from operating in a normal fashion.

	Think twice before using Disable(), then think once more.
	After all that, think again.  With enough thought, the need
	for a Disable() can often be eliminated.  For the user of many
	device drivers, a write to disable *only* the particular interrupt
	of interest can replace a Disable().  For example:
			MOVE.W	#INTF_PORTS,_intena
	Do not use a macro for Disable(), insist on the real thing.

	This call may be made from interrupts, it will have the effect
	of locking out all higher-level interrupts (lower-level interrupts
	are automatically disabled by the CPU).

        Note: In the event of a task entering a @{"Wait()" Link "Wait()"} after disabling
              interrupts, the system "breaks" the disabled state and runs
              normally until the task which called Disable() is rescheduled.

@{b}    NOTE@{ub}
	This call is guaranteed to preserve all registers.

@{b}    SEE ALSO@{ub}
	@{"Forbid" Link "exec/Forbid()"}, @{"Permit" Link "exec/Permit()"}, @{"Enable" Link "exec/Enable()"}

@EndNode

@Node "DoIO()" "exec.library/DoIO"

@{b}   NAME@{ub}
	DoIO -- perform an I/O command and wait for completion

@{b}   SYNOPSIS@{ub}
	error = DoIO(iORequest)
	D0	     A1

	@{"BYTE" Link "INCLUDE:exec/types.h/Main" 118} DoIO(struct @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} *);

@{b}   FUNCTION@{ub}
	This function requests a device driver to perform the I/O command
	specified in the I/O request.  This function will always wait until
	the I/O request is fully complete.

	DoIO() handles all the details, including Quick I/O, waiting for
	the request, and removing the reply message, etc..

@{b}   IMPLEMENTATION@{ub}
	This function first tries to complete the IO via the "Quick I/O"
	mechanism.  The io_Flags field is always set to IOF_QUICK (0x01)
	before the internal device call.

	The io_Message.mn_Node.ln_Type field is used internally to flag
	completion.  Active requests have type NT_MESSAGE.  Requests
	that have been replied have type NT_REPLYMSG or (rarely) NT_FREEMSG.
	It is illegal to start IO using a still active @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16}, or a
	request with type NT_REPLYMSG.

@{b}   INPUTS@{ub}
	iORequest - pointer to an @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} initialized by @{"OpenDevice()" Link "OpenDevice()"}

@{b}   RESULTS@{ub}
	error - a sign-extended copy of the io_Error field of the
		@{"IORequest" Link "INCLUDE:exec/io.h/Main" 16}.  Most device commands require that the error
		return be checked.

@{b}   SEE ALSO@{ub}
	@{"SendIO" Link "exec/SendIO()"}, @{"CheckIO" Link "exec/CheckIO()"}, @{"WaitIO" Link "exec/WaitIO()"}, @{"AbortIO" Link "timer/AbortIO()"}, @{"ReplyMsg" Link "exec/ReplyMsg()"}, @{"amiga.lib/BeginIO" Link "serial/BeginIO()"}

@EndNode

@Node "Enable()" "exec.library/Enable"

@{b}   NAME@{ub}
	Enable -- permit system interrupts to resume.

@{b}   SYNOPSIS@{ub}
	Enable();

	void Enable(void);

@{b}   FUNCTION@{ub}
	Allow system interrupts to again occur normally, after a matching
	@{"Disable()" Link "Disable()"} has been executed.

@{b}   RESULTS@{ub}
	@{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} processing is restored to normal operation. The
	programmer must execute exactly one call to Enable() for every call
	to @{"Disable()" Link "Disable()"}.

@{b}    NOTE@{ub}
	This call is guaranteed to preserve all registers.

@{b}   SEE ALSO@{ub}
	@{"Forbid" Link "exec/Forbid()"}, @{"Permit" Link "exec/Permit()"}, @{"Disable" Link "exec/Disable()"}


@EndNode

@Node "Enqueue()" "exec.library/Enqueue"

@{b}   NAME@{ub}
	Enqueue -- insert or append node to a system queue

@{b}   SYNOPSIS@{ub}
	Enqueue(list, node)
		A0    A1

	void Enqueue(struct @{"List" Link "INCLUDE:exec/lists.h/Main" 19} *, struct @{"Node" Link "INCLUDE:exec/nodes.h/Main" 21} *);

@{b}   FUNCTION@{ub}
	@{"Insert" Link "exec/Insert()"} or append a node into a system queue.  The insertion is
	performed based on the node priority -- it will keep the list
	properly sorted.  New nodes will be inserted in front of the first
	node with a lower priority.   Hence a FIFO queue for nodes of equal
	priority

@{b}   WARNING@{ub}
	This function does not arbitrate for access to the list.  The
	calling task must be the owner of the involved list.

@{b}   INPUTS@{ub}
	list - a pointer to the system queue header
	node - the node to enqueue.  This must be a full featured node
	       with type, priority and name fields.

@{b}   SEE ALSO@{ub}
	@{"AddHead" Link "exec/AddHead()"}, @{"AddTail" Link "exec/AddTail()"}, @{"Insert" Link "exec/Insert()"}, @{"Remove" Link "exec/Remove()"}, @{"RemHead" Link "exec/RemHead()"}, @{"RemTail" Link "exec/RemTail()"}

@EndNode

@Node "FindName()" "exec.library/FindName"

@{b}   NAME@{ub}
	FindName -- find a system list node with a given name

@{b}   SYNOPSIS@{ub}
	node = FindName(start, name)
	D0,Z		A0     A1

	struct @{"Node" Link "INCLUDE:exec/nodes.h/Main" 21} *FindName(struct @{"List" Link "INCLUDE:exec/lists.h/Main" 19} *, STRPTR);

@{b}   FUNCTION@{ub}
	Traverse a system list until a node with the given name is found.
	To find multiple occurrences of a string, this function may be
	called with a node starting point.

	No arbitration is done for access to the list!	If multiple tasks
	access the same list, an arbitration mechanism such as
	SignalSemaphores must be used.

@{b}   INPUTS@{ub}
	start - a list header or a list node to start the search
		(if node, this one is skipped)
	name - a pointer to a name string terminated with @{"NULL" Link "rexxsupport/NULL"}

@{b}   RESULTS@{ub}
	node - a pointer to the node with the same name else
	    zero to indicate that the string was not found.

@EndNode

@Node "FindPort()" "exec.library/FindPort"

@{b}   NAME@{ub}
	FindPort -- find a given system message port

@{b}   SYNOPSIS@{ub}
	port = FindPort(name)
	D0		A1

	struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} *FindPort(STRPTR);

@{b}   FUNCTION@{ub}
	This function will search the system message port list for a port
	with the given name.  The first port matching this name will be
	returned.  No arbitration of the port list is done.  This function
	MUST be protected with A @{"Forbid()/Permit()" Link "Permit()"} pair!

@{b}   EXAMPLE@{ub}
	#include @{"<exec/types.h>" Link "INCLUDE:exec/types.h/Main" 0}
	struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} *FindPort();

	ULONG SafePutToPort(message, portname)
	struct @{"Message" Link "INCLUDE:exec/ports.h/Main" 45} *message;
	@{"STRPTR" Link "INCLUDE:exec/types.h/Main" 137}          portname;
	{
	struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} *port;

	    Forbid();
		port = FindPort(portname);
		if (port != NULL)
		    PutMsg(port,message);
	    Permit();
	    return((ULONG)port); /* If zero, the port has gone away */
	}

@{b}   INPUT@{ub}
	name - name of the port to find

@{b}   RETURN@{ub}
	port - a pointer to the message port, or zero if
		not found.


@EndNode

@Node "FindResident()" "exec.library/FindResident"

@{b}   NAME@{ub}
	FindResident - find a resident module by name

@{b}   SYNOPSIS@{ub}
	resident = FindResident(name)
	D0			A1

	struct @{"Resident" Link "INCLUDE:exec/resident.h/Main" 16} *FindResident(STRPTR);

@{b}   FUNCTION@{ub}
	Search the system resident tag list for a resident tag ("ROMTag") with
	the given name.  If found return a pointer to the resident tag
	structure, else return zero.

	@{"Resident" Link "INCLUDE:exec/resident.h/Main" 16} modules are used by the system to pull all its parts
	together at startup.  @{"Resident" Link "INCLUDE:exec/resident.h/Main" 16} tags are also found in disk based
	devices and libraries.

@{b}   INPUTS@{ub}
	name - pointer to name string

@{b}   RESULT@{ub}
	resident - pointer to the resident tag structure or
		zero if none found.

@{b}    SEE ALSO@{ub}
	@{"exec/resident.h" Link "INCLUDE:exec/resident.h/Main" 0}, @{"InitResident" Link "exec/InitResident()"}

@EndNode

@Node "FindSemaphore()" "exec.library/FindSemaphore"

@{b}   NAME@{ub}
	FindSemaphore -- find a given system signal semaphore

@{b}   SYNOPSIS@{ub}
	signalSemaphore = FindSemaphore(name)
	D0		                A1

	struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *FindSemaphore(STRPTR);

@{b}   FUNCTION@{ub}
	This function will search the system signal semaphore list for a
	semaphore with the given name.	The first semaphore matching this
	name will be returned.

	This function does not arbitrate for access to the semaphore list,
	surround the call with a @{"Forbid()/Permit()" Link "Permit()"} pair.

@{b}   INPUT@{ub}
	name - name of the semaphore to find

@{b}   RESULT@{ub}
	semaphore - a pointer to the signal semaphore, or zero if not
		    found.

@EndNode

@Node "FindTask()" "exec.library/FindTask"

@{b}   NAME@{ub}
	FindTask -- find a task with the given name or find oneself

@{b}   SYNOPSIS@{ub}
	task = FindTask(name)
	D0		A1

	struct @{"Task" Link "INCLUDE:exec/tasks.h/Main" 23} *FindTask(STRPTR);

@{b}   FUNCTION@{ub}
	This function will check all task queues for a task with the given
	name, and return a pointer to its task control block.  If a @{"NULL" Link "rexxsupport/NULL"}
	name pointer is given a pointer to the current task will be
	returned.

	Finding oneself with a @{"NULL" Link "rexxsupport/NULL"} for the name is very quick.  Finding a
	task by name is very system expensive, and will disable interrupts
	for a long time.  Since a task may remove itself at any time,
	a @{"Forbid()/Permit()" Link "Permit()"} pair may be needed to ensure the pointer
	returned by FindTask() is still valid when used.

@{b}   INPUT@{ub}
	name - pointer to a name string

@{b}   RESULT@{ub}
	task - pointer to the task (or Process)

@EndNode

@Node "Forbid()" "exec.library/Forbid"

@{b}    NAME@{ub}
	Forbid -- forbid task rescheduling.

@{b}    SYNOPSIS@{ub}
	Forbid()

	void Forbid(void);

@{b}    FUNCTION@{ub}
	Prevents other tasks from being scheduled to run by the dispatcher,
	until a matching @{"Permit()" Link "Permit()"} is executed, or this task is scheduled to
	@{"Wait()" Link "Wait()"}.  Interrupts are NOT disabled.

	DO NOT USE THIS CALL WITHOUT GOOD JUSTIFICATION.  THIS CALL IS
	DANGEROUS!

@{b}    RESULTS@{ub}
	The current task will not be rescheduled as long as it is ready to
	run.  In the event that the current task enters a wait state, other
	tasks may be scheduled.  Upon return from the wait state, the original
	task will continue to run without disturbing the Forbid().

	Calls to Forbid() nest. In order to restore normal task rescheduling,
	the programmer must execute exactly one call to @{"Permit()" Link "Permit()"} for every
	call to Forbid().

@{b}    WARNING@{ub}
	In the event of a task entering a @{"Wait()" Link "Wait()"} after a Forbid(), the system
	"breaks" the forbidden state and runs normally until the task which
	called Forbid() is rescheduled.  If caution is not taken, this can
	cause subtle bugs, since any device or DOS call will (in effect)
	cause your task to wait.

	Forbid() is not useful or safe from within interrupt code
	(All interrupts are always higher priority than tasks, and
	interrupts are allowed to break a Forbid()).

@{b}    NOTE@{ub}
	This call is guaranteed to preserve all registers.

@{b}    SEE ALSO@{ub}
	@{"Permit" Link "exec/Permit()"}, @{"Disable" Link "exec/Disable()"}, @{"ObtainSemaphore" Link "exec/ObtainSemaphore()"}, @{"ObtainSemaphoreShared" Link "exec/ObtainSemaphoreShared()"}

@EndNode

@Node "FreeEntry()" "exec.library/FreeEntry"

@{b}   NAME@{ub}
	FreeEntry -- free many regions of memory

@{b}   SYNOPSIS@{ub}
	FreeEntry(memList)
		  A0
	void FreeEntry(struct @{"MemList" Link "INCLUDE:exec/memory.h/Main" 54} *);

@{b}   FUNCTION@{ub}
	This function takes a memList structure (as returned by AllocEntry)
	and frees all the entries.

@{b}   INPUTS@{ub}
	memList -- pointer to structure filled in with @{"MemEntry" Link "INCLUDE:exec/memory.h/Main" 38}
		   structures

@{b}   SEE ALSO@{ub}
	@{"AllocEntry" Link "exec/AllocEntry()"}

@EndNode

@Node "FreeMem()" "exec.library/FreeMem"

@{b}   NAME@{ub}
	FreeMem -- deallocate with knowledge

@{b}   SYNOPSIS@{ub}
	FreeMem(memoryBlock, byteSize)
		A1	     D0

	void FreeMem(void *,ULONG);

@{b}   FUNCTION@{ub}
	Free a region of memory, returning it to the system pool from which
	it came.  Freeing partial blocks back into the system pool is
	unwise.

@{b}   NOTE@{ub}
	If a block of memory is freed twice, the system will Guru. The
	@{"Alert" Link "exec/Alert()"} is AN_FreeTwice ($01000009).   If you pass the wrong pointer,
	you will probably see AN_MemCorrupt $01000005.  Future versions may
	add more sanity checks to the memory lists.

@{b}   INPUTS@{ub}
	memoryBlock - pointer to the memory block to free
	byteSize - the size of the desired block in bytes.  (The operating
		system will automatically round this number to a multiple of
		the system memory chunk size)

@{b}   SEE ALSO@{ub}
	@{"AllocMem" Link "exec/AllocMem()"}

@EndNode

@Node "FreePooled()" "exec.library/FreePooled"

@{b}    NAME@{ub}
	FreePooled -- Free pooled memory  (V39)

@{b}    SYNOPSIS@{ub}
	FreePooled(poolHeader,memory,memSize)
		   a0         a1     d0

	void FreePooled(APTR,@{"APTR" Link "INCLUDE:exec/types.h/Main" 75},ULONG);

@{b}    FUNCTION@{ub}
	Deallocates memory allocated by @{"AllocPooled()" Link "AllocPooled()"}.  The size of the
	allocation *MUST* match the size given to @{"AllocPooled()" Link "AllocPooled()"}.
	The reason the pool functions do not track individual allocation
	sizes is because many of the uses of pools have small allocation
	sizes and the tracking of the size would be a large overhead.

	Only memory allocated by @{"AllocPooled()" Link "AllocPooled()"} may be freed with this
	function!

	Doing a @{"DeletePool()" Link "DeletePool()"} on the pool will free all of the puddles
	and thus all of the allocations done with @{"AllocPooled()" Link "AllocPooled()"} in that
	pool.  (No need to FreePooled() each allocation)

@{b}    INPUTS@{ub}
	poolHeader - a specific private pool header.
	memory - pointer to memory allocated by @{"AllocPooled" Link "exec/AllocPooled()"}.
	memSize - the number of bytes allocated by @{"AllocPooled" Link "exec/AllocPooled()"}.
	    THIS MUST NEVER BE 0!

@{b}    NOTES@{ub}
	The pool functions do not protect an individual pool from
	multiple accesses.  The reason is that in most cases the pools
	will be used by a single task.  If your pool is going to
	be used by more than one task you must Semaphore protect
	the pool from having more than one task trying to allocate
	within the same pool at the same time.  Warning:  @{"Forbid()" Link "Forbid()"}
	protection *will not work* in the future.  *Do NOT* assume
	that we will be able to make it work in the future.  FreePooled()
	may well break a @{"Forbid()" Link "Forbid()"} and as such can only be protected
	by a semaphore.

	The size of the memory allocation to be freed must match
	the size used when @{"AllocPooled()" Link "AllocPooled()"} was called. A mismatch may
	result in memory corruption or in memory remaining allocated
	which not even @{"DeletePool()" Link "DeletePool()"} can release. THE SIZE OF THE MEMORY
	ALLOCATION MUST NEVER BE 0, OR INSTANT MEMORY CORRUPTION IS
	LIKELY TO FOLLOW!

	If the address and allocation size cannot be matched against
	a puddle or large allocation which is part of the pool, an
	alert of type AN_BadFreeAddr will be triggered.

	To track sizes yourself, the following code can be used:
	Assumes a6=ExecBase

	;
	; Function to do AllocVecPooled(Pool,memSize)
	;
	AllocVecPooled:	addq.l	#4,d0		; Get space for tracking
			move.l	d0,-(sp)	; Save the size
			jsr	_LVOAllocPooled(a6)	; Call pool...
			move.l	(sp)+,d1	; Get size back...
			tst.l	d0		; Check for error
			beq.s	avp_fail	; If @{"NULL" Link "rexxsupport/NULL"}, failed!
			move.l	d0,a0		; Get pointer...
			move.l	d1,(a0)+	; Store size
			move.l	a0,d0		; Get result
	avp_fail:	rts			; return

	;
	; Function to do FreeVecPooled(pool,memory)
	;
	FreeVecPooled:	move.l	-(a1),d0	; Get size / ajust pointer
			jmp	_LVOFreePooled(a6)

@{b}    SEE ALSO@{ub}
	@{"AllocPooled()" Link "AllocPooled()"}, @{"CreatePool()" Link "CreatePool()"}, @{"DeletePool()" Link "DeletePool()"}, @{"exec/alerts.h" Link "INCLUDE:exec/alerts.h/Main" 0}

@EndNode

@Node "FreeSignal()" "exec.library/FreeSignal"

@{b}   NAME@{ub}
	FreeSignal -- free a signal bit

@{b}   SYNOPSIS@{ub}
	FreeSignal(signalNum)
		   D0

	void FreeSignal(BYTE);

@{b}   FUNCTION@{ub}
	This function frees a previously allocated signal bit for reuse.
	This call must be performed while running in the same task in which
	the signal was allocated.

@{b}   WARNING@{ub}
	Signals may not be allocated or freed from exception handling code.

@{b}   NOTE@{ub}
	Starting with V37, an attempt to free signal -1 is harmless.

@{b}   INPUTS@{ub}
	signalNum - the signal number to free {0..31}.

@EndNode

@Node "FreeTrap()" "exec.library/FreeTrap"

@{b}   NAME@{ub}
	FreeTrap -- free a processor trap

@{b}   SYNOPSIS@{ub}
	FreeTrap(trapNum)
		 D0

	void FreeTrap(ULONG);

@{b}   FUNCTION@{ub}
	This function frees a previously allocated trap number for reuse.
	This call must be performed while running in the same task in which
	the trap was allocated.

@{b}   WARNING@{ub}
	Traps may not be allocated or freed from exception handling code.

@{b}   INPUTS@{ub}
	trapNum - the trap number to free {of 0..15}

@EndNode

@Node "FreeVec()" "exec.library/FreeVec"

@{b}   NAME@{ub}
	FreeVec -- return @{"AllocVec()" Link "AllocVec()"} memory to the system  (V36)

@{b}   SYNOPSIS@{ub}
	FreeVec(memoryBlock)
		A1

	void FreeVec(void *);

@{b}   FUNCTION@{ub}
	Free an allocation made by the @{"AllocVec()" Link "AllocVec()"} call.  The memory will
	be returned to the system pool from which it came.

@{b}   NOTE@{ub}
	If a block of memory is freed twice, the system will Guru. The
	@{"Alert" Link "exec/Alert()"} is AN_FreeTwice ($01000009).   If you pass the wrong pointer,
	you will probably see AN_MemCorrupt $01000005.  Future versions may
	add more sanity checks to the memory lists.

@{b}   INPUTS@{ub}
	memoryBlock - pointer to the memory block to free, or @{"NULL" Link "rexxsupport/NULL"}.

@{b}   SEE ALSO@{ub}
	@{"AllocVec" Link "exec/AllocVec()"}

@EndNode

@Node "GetCC()" "exec.library/GetCC"

@{b}   NAME@{ub}
	GetCC -- get condition codes in a 68010 compatible way.

@{b}   SYNOPSIS@{ub}
	conditions = GetCC()
	  D0

	@{"UWORD" Link "INCLUDE:exec/types.h/Main" 116} GetCC(void);

@{b}   FUNCTION@{ub}
	The 68000 processor has a "MOVE SR,<ea>" instruction which gets a
	copy of the processor condition codes.

	On the 68010,20 and 30 CPUs, "MOVE SR,<ea>" is privileged.  User
	code will trap if it is attempted.  These processors need to use
	the "MOVE CCR,<ea>" instruction instead.

	This function provides a means of obtaining the CPU condition codes
	in a manner that will make upgrades transparent.  This function is
	VERY short and quick.

@{b}   RESULTS@{ub}
	conditions - the 680XX condition codes

@{b}    NOTE@{ub}
	This call is guaranteed to preserve all registers.  This function
	may be implemented as code right in the jump table.

@EndNode

@Node "GetMsg()" "exec.library/GetMsg"

@{b}   NAME@{ub}
	GetMsg -- get next message from a message port

@{b}   SYNOPSIS@{ub}
	message = GetMsg(port)
	D0		 A0

	struct @{"Message" Link "INCLUDE:exec/ports.h/Main" 45} *GetMsg(struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} *);

@{b}   FUNCTION@{ub}
	This function receives a message from a given message port. It
	provides a fast, non-copying message receiving mechanism. The
	received message is removed from the message port.

	This function will not wait.  If a message is not present this
	function will return zero.  If a program must wait for a message,
	it can @{"Wait()" Link "Wait()"} on the signal specified for the port or use the
	@{"WaitPort()" Link "WaitPort()"} function.  There can only be one task waiting for any
	given port.

	Getting a message does not imply to the sender that the message is
	free to be reused by the sender.  When the receiver is finished
	with the message, it may @{"ReplyMsg()" Link "ReplyMsg()"} it back to the sender.


	Getting a signal does NOT always imply a message is ready.  More
	than one message may arrive per signal, and signals may show up
	without messages.  Typically you must loop to GetMsg() until it
	returns zero, then @{"Wait()" Link "Wait()"} or @{"WaitPort()" Link "WaitPort()"}.

@{b}   INPUT@{ub}
	port - a pointer to the receiver message port

@{b}   RESULT@{ub}
	message - a pointer to the first message available.  If
		  there are no messages, return zero.
		  Callers must be prepared for zero at any time.

@{b}   SEE ALSO@{ub}
	@{"PutMsg" Link "exec/PutMsg()"}, @{"ReplyMsg" Link "exec/ReplyMsg()"}, @{"WaitPort" Link "exec/WaitPort()"}, @{"Wait" Link "exec/Wait()"}, @{"exec/ports.h" Link "INCLUDE:exec/ports.h/Main" 0}

@EndNode

@Node "InitCode()" "exec.library/InitCode"

@{b}   NAME@{ub}
	InitCode - initialize resident code modules (internal function)

@{b}   SYNOPSIS@{ub}
	InitCode(startClass, version)
		 D0          D1

	void InitCode(ULONG,ULONG);

@{b}   FUNCTION@{ub}
	(This function may be ignored by application programmers)

	Call @{"InitResident()" Link "InitResident()"} for all resident modules in the ResModules array
	with the given startClass and with versions equal or greater than
	that specified.  The segList parameter is passed as zero.

	@{"Resident" Link "INCLUDE:exec/resident.h/Main" 16} modules are used by the system to pull all its parts
	together at startup.  Modules are initialized in a prioritized order.

	Modules that do not have a startclass should be of priority -120.
	RTF_AFTERDOS modules should start at -100 (working down).

@{b}   INPUTS@{ub}
	startClass - the class of code to be initialized:
		BITDEF RT,COLDSTART,0
		BITDEF RT,SINGLETASK,1	;ExecBase->ThisTask==0 (V36 only)
		BITDEF RT,AFTERDOS,2	;(V36 only)
	version - a major version number

@{b}    SEE ALSO@{ub}
	ResidentTag (RT) structure definition (resident.h)

@EndNode

@Node "InitResident()" "exec.library/InitResident"

@{b}   NAME@{ub}
	InitResident - initialize resident module

@{b}   SYNOPSIS@{ub}
	object = InitResident(resident, segList)
	D0	               A1        D1

	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75} InitResident(struct @{"Resident" Link "INCLUDE:exec/resident.h/Main" 16} *,ULONG);

@{b}   FUNCTION@{ub}
	Initialize a ROMTag.  ROMTags are used to link system modules
	together.  Each disk based device or library must contain a
	ROMTag structure in the first code hunk.

	Once the validity of the ROMTag is verified, the RT_INIT pointer
	is jumped to  with the following registers:
		D0 = 0
		A0 = segList
	 	A6 = @{"ExecBase" Link "INCLUDE:exec/execbase.h/Main" 32}

@{b}   INPUTS@{ub}
	resident - Pointer to a ROMTag
	segList  - SegList of the loaded object, if loaded from disk.
		   Libraries & Devices will cache this value for later
		   return at close or expunge time.  Pass @{"NULL" Link "rexxsupport/NULL"} for ROM
		   modules.

@{b}   RESULTS@{ub}
	object	- Return value from the init code, usually the library
		  or device base.  @{"NULL" Link "rexxsupport/NULL"} for failure.

@{b}   AUTOINIT FEATURE@{ub}
	An automatic method of library/device base and vector table
	initialization is also provided by InitResident().  The initial code
	hunk of the library or device should contain "MOVEQ #-1,d0; RTS;".
	Following that must be an initialized @{"Resident" Link "INCLUDE:exec/resident.h/Main" 16} structure with
	RTF_AUTOINIT set in rt_Flags, and an rt_Init pointer which points
	to four longwords.  These four longwords will be used in a call
	to MakeLibrary();

	    - The size of your library/device base structure including initial
	      @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} or @{"Device" Link "INCLUDE:exec/devices.h/Main" 23} structure.

	    - A pointer to a longword table of standard, then library
	      specific function offsets, terminated with -1L.
	      (short format offsets are also acceptable)

	    - Pointer to data table in @{"exec/InitStruct" Link "exec/InitStruct()"} format for
	      initialization of @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} or @{"Device" Link "INCLUDE:exec/devices.h/Main" 23} structure.

	    - Pointer to library initialization function, or @{"NULL" Link "rexxsupport/NULL"}.
		Calling sequence:
			D0 = library base
			A0 = segList
			A6 = @{"ExecBase" Link "INCLUDE:exec/execbase.h/Main" 32}
	      This function must return in D0 the library/device base to be
	      linked into the library/device list.  If the initialization
	      function fails, the device memory must be manually deallocated,
	      then @{"NULL" Link "rexxsupport/NULL"} returned in D0.

@{b}   SEE ALSO@{ub}
	exec/resident.i, @{"FindResident" Link "exec/FindResident()"}

@EndNode

@Node "InitSemaphore()" "exec.library/InitSemaphore"

@{b}   NAME@{ub}
	InitSemaphore -- initialize a signal semaphore

@{b}   SYNOPSIS@{ub}
	InitSemaphore(signalSemaphore)
		      A0

	void InitSemaphore(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *);

@{b}   FUNCTION@{ub}
	This function initializes a signal semaphore and prepares it for
	use.  It does not allocate anything, but does initialize list
	pointers and the semaphore counters.

	Semaphores are often used to protect critical data structures
	or hardware that can only be accessed by one task at a time.
	After initialization, the address of the @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} may be
	made available to any number of tasks.  Typically a task will
	try to @{"ObtainSemaphore()" Link "ObtainSemaphore()"}, passing this address in.  If no other
	task owns the semaphore, then the call will lock and return
	quickly.  If more tasks try to @{"ObtainSemaphore()" Link "ObtainSemaphore()"}, they will
	be put to sleep.  When the owner of the semaphore releases
	it, the next waiter in turn will be woken up.

	Semaphores are often preferable to the old-style @{"Forbid()/Permit()" Link "Permit()"}
	type arbitration.  With @{"Forbid()/Permit()" Link "Permit()"} *all* other tasks are
	prevented from running.  With semaphores, only those tasks that
	need access to whatever the semaphore protects are subject
	to waiting.

@{b}   INPUT@{ub}
	signalSemaphore -- a signal semaphore structure (with all fields
			   set to zero before the call)

@{b}   SEE ALSO@{ub}
	@{"ObtainSemaphore" Link "exec/ObtainSemaphore()"}, @{"ObtainSemaphoreShared" Link "exec/ObtainSemaphoreShared()"}, @{"AttemptSemaphore" Link "exec/AttemptSemaphore()"},
	@{"ReleaseSemaphore" Link "exec/ReleaseSemaphore()"}, @{"Procure" Link "exec/Procure()"}, @{"Vacate" Link "exec/Vacate()"}, @{"exec/semaphores.h" Link "INCLUDE:exec/semaphores.h/Main" 0}

@EndNode

@Node "InitStruct()" "exec.library/InitStruct"

@{b}   NAME@{ub}
	InitStruct - initialize memory from a table

@{b}   SYNOPSIS@{ub}
	InitStruct(initTable, memory, size);
		   A1	      A2      D0

	void InitStruct(struct InitStruct *, @{"APTR" Link "INCLUDE:exec/types.h/Main" 75}, ULONG);

@{b}   FUNCTION@{ub}
	Clear a memory area, then set up default values according to
	the data and offset values in the initTable.  Typically only assembly
	programs take advantage of this function, and only with the macros
	defined in "exec/initializers.i".

	The initialization table has byte commands to

	     |a    ||byte|	|given||byte|	      |once	    |
	load |count||word| into |next ||rptr| offset, |repetitively |
		    |long|

	Not all combinations are supported.  The offset, when specified, is
	relative to the memory pointer provided (Memory), and is initially
	zero.  The initialization data (InitTable) contains byte commands
	whose 8 bits are interpreted as follows:

	ddssnnnn
	    dd	the destination type (and size):
		00  no offset, use next destination, nnnn is count
		01  no offset, use next destination, nnnn is repeat
		10  destination offset is in the next byte, nnnn is count
		11  destination offset is in the next 24-bits, nnnn is count
	    ss	the size and location of the source:
		00  long, from the next two aligned words
		01  word, from the next aligned word
		10  byte, from the next byte
		11  ERROR - will cause an ALERT (see below)
	  nnnn	the count or repeat:
	     count  the (number+1) of source items to copy
	    repeat  the source is copied (number+1) times.

	initTable commands are always read from the next even byte. Given
	destination offsets are always relative to the memory pointer (A2).

	The command %00000000 ends the InitTable stream: use %00010001 if you
	really want to copy one longword without a new offset.

	24 bit @{"APTR" Link "INCLUDE:exec/types.h/Main" 75} not supported for 68020 compatibility -- use long.

@{b}   INPUTS@{ub}
	initTable - the beginning of the commands and data to init
		Memory with.  Must be on an even boundary unless only
		byte initialization is done.  End table with "dc.b 0"
		or "dc.w 0".
	memory - the beginning of the memory to initialize.  Must be
		on an even boundary if size is specified.
	size - the size of memory, which is used to clear it before
		initializing it via the initTable.  If Size is zero,
		memory is not cleared before initializing.

		size must be an even number.

@{b}    SEE ALSO@{ub}
	exec/initializers.i

@EndNode

@Node "Insert()" "exec.library/Insert"

@{b}   NAME@{ub}
	Insert -- insert a node into a list

@{b}   SYNOPSIS@{ub}
	Insert(list, node, listNode)
	       A0    A1    A2

	void Insert(struct @{"List" Link "INCLUDE:exec/lists.h/Main" 19} *, struct @{"Node" Link "INCLUDE:exec/nodes.h/Main" 21} *, struct @{"Node" Link "INCLUDE:exec/nodes.h/Main" 21} *);

@{b}   FUNCTION@{ub}
	Insert a node into a doubly linked list AFTER a given node
	position.  Insertion at the head of a list is possible by passing a
	zero value for listNode, though the @{"AddHead" Link "exec/AddHead()"} function is slightly
	faster for that special case.

@{b}   WARNING@{ub}
	This function does not arbitrate for access to the list.  The
	calling task must be the owner of the involved list.

@{b}   INPUTS@{ub}
	list - a pointer to the target list header
	node - the node to insert
	listNode - the node after which to insert

@{b}    SEE ALSO@{ub}
	@{"AddHead" Link "exec/AddHead()"}, @{"AddTail" Link "exec/AddTail()"}, @{"Enqueue" Link "exec/Enqueue()"}, @{"RemHead" Link "exec/RemHead()"}, @{"Remove" Link "exec/Remove()"}, @{"RemTail" Link "exec/RemTail()"}

@EndNode

@Node "MakeFunctions()" "exec.library/MakeFunctions"

@{b}   NAME@{ub}
	MakeFunctions -- construct a function jump table

@{b}   SYNOPSIS@{ub}
	tableSize = MakeFunctions(target, functionArray, funcDispBase)
	D0			  A0	  A1		 A2

	ULONG MakeFunctions(APTR,@{"APTR" Link "INCLUDE:exec/types.h/Main" 75},APTR);

@{b}   FUNCTION@{ub}
	A low level function used by @{"MakeLibrary" Link "exec/MakeLibrary()"} to build jump tables of
	the type used by libraries, devices and resources.  It allows the
	table to be built anywhere in memory, and can be used both for
	initialization and replacement. This function also supports function
	pointer compression by expanding relative displacements into absolute
	pointers.

	The processor instruction cache is cleared after the table building.

@{b}   INPUT@{ub}
	destination - the target address for the high memory end of the
		function jump table.  Typically this will be the library
		base pointer.

	functionArray - pointer to an array of function pointers or
		function displacements.  If funcDispBase is zero, the array
		is assumed to contain absolute pointers to functions. If
		funcDispBase is not zero, then the array is assumed to
		contain word displacements to functions.  In both cases,
		the array is terminated by a -1 (of the same size as the
		actual entry.

	funcDispBase - pointer to the base about which all function
		displacements are relative.  If zero, then the function
		array contains absolute pointers.

@{b}   RESULT@{ub}
	tableSize - size of the new table in bytes (for LIB_NEGSIZE).

@{b}   SEE ALSO@{ub}
	@{"exec/MakeLibrary" Link "exec/MakeLibrary()"}

@EndNode

@Node "MakeLibrary()" "exec.library/MakeLibrary"

@{b}   NAME@{ub}
	MakeLibrary -- construct a library

@{b}   SYNOPSIS@{ub}
	library = MakeLibrary(vectors, structure, init, dSize, segList)
	D0		      A0       A1	  A2	D0     D1

	struct @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} *MakeLibrary
			      (APTR,struct @{"InitStruct" Link "exec/InitStruct()"} *,@{"APTR" Link "INCLUDE:exec/types.h/Main" 75},ULONG,BPTR);

@{b}   FUNCTION@{ub}
	This function is used for constructing a library vector and data
	area.  The same call is used to make devices.  Space for the library
	is allocated from the system's free memory pool.  The data portion of
	the library is initialized.  init may point to a library specific
	entry point.

@{b}   NOTE@{ub}
	Starting with V36, the library base is longword adjusted.  The
	lib_PosSize and lib_NegSize fields of the library structure are
	adjusted to match.

@{b}   INPUTS@{ub}
	vectors - pointer to an array of function pointers or function
		displacements.	If the first word of the array is -1, then
		the array contains relative word displacements (based off
		of vectors); otherwise, the array contains absolute
		function pointers. The vector list is terminated by a -1
		(of the same size as the pointers).

	structure - points to an "InitStruct" data region.  If @{"NULL" Link "rexxsupport/NULL"},
		then it will not be used.

	init -	If non-NULL, an entry point that will be called before adding
		the library to the system.  Registers are as follows:
			d0 = libAddr 	;Your @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} Address
			a0 = segList	;Your AmigaDOS segment list
			a6 = @{"ExecBase" Link "INCLUDE:exec/execbase.h/Main" 32}	;Address of exec.library
		The result of the init function must be the library address,
		or @{"NULL" Link "rexxsupport/NULL"} for failure.   If @{"NULL" Link "rexxsupport/NULL"}, the init point must manually
		deallocate the library base memory (based on the sizes stored
		in lib_PosSize and lib_NegSize).

	dSize - the size of the library data area, including the
		standard library node data.  This must be at leas
		sizeof(struct Library).

       segList - pointer to an AmigaDOS SegList (segment list).
		 This is passed to a library's init code, and is used later
		 for removing the library from memory.

@{b}   RESULT@{ub}
	library - the reference address of the library.  This is the
		  address used in references to the library, not the
		  beginning of the memory area allocated.  If the library
		  vector table require more system memory than is
		  available, this function will return @{"NULL" Link "rexxsupport/NULL"}.

@{b}   SEE ALSO@{ub}
	@{"InitStruct" Link "exec/InitStruct()"}, @{"InitResident" Link "exec/InitResident()"}, exec/initializers.i

@EndNode

@Node "NewMinList()" "exec.library/NewMinList"

@{b}   NAME@{ub}
	NewMinList -- prepare a list structure for use (V45)

@{b}   SYNOPSIS@{ub}
	NewMinList(list)

	VOID NewMinList(struct @{"MinList" Link "INCLUDE:exec/lists.h/Main" 30} *);

@{b}   FUNCTION@{ub}
	Perform the magic needed to prepare a @{"MinList" Link "INCLUDE:exec/lists.h/Main" 30} header structure for
	use; the list will be empty and ready to use. You can use this
	function with a pointer to a 'struct List', too, but you may have
	to initialize the List->lh_Type as well.

@{b}   INPUTS@{ub}
	list - pointer to a @{"List" Link "INCLUDE:exec/lists.h/Main" 19} or @{"MinList" Link "INCLUDE:exec/lists.h/Main" 30}.

@{b}   SEE ALSO@{ub}
	@{"<exec/lists.h>" Link "INCLUDE:exec/lists.h/Main" 0}

@EndNode

@Node "ObtainQuickVector()" "exec.library/ObtainQuickVector"

@{b}   NAME@{ub}
	Function to obtain an install a Quick @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} vector            (V39)

@{b}   SYNOPSIS@{ub}
	vector=ObtainQuickVector(interruptCode)
	d0                       a0

	ULONG ObtainQuickVector(APTR);

@{b}   FUNCTION@{ub}
	This function will install the code pointer into the quick interrupt
	vector it allocates and returns to you the interrupt vector that
	your Quick @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} system needs to use.

	This function may also return 0 if no vectors are available.  Your
	hardware should be able to then fall back to using the shared
	interrupt server chain should this happen.

	The interrupt code is a direct connect to the physical interrupt.
	This means that it is the responsibility of your code to do all
	of the context saving/restoring required by interrupt code.

	Also, due to the performance of the interrupt controller, you may
	need to also watch for "false" interrupts.  These are interrupts
	that come in just after a DISABLE.  The reason this happens is
	because the interrupt may have been posted before the DISABLE
	hardware access is completed.  For example:

	myInt:		move.l	d0,-(sp)	; Save d0...
			move.w	_intenar,d0	; Get interrupt enable state
			btst.l	#INTB_INTEN,d0	; Check if pending disable
			bne.s	realInt		; If not, do real one...
	exitInt:	move.l	(sp)+,d0	; Restore d0
			rte			; Return from int...
	;
	realInt:	; Now do your int code...  d0 is already saved
			; ALL other registers need to be saved if needed
			; This includes a0/a1/d0/d1 as this is an interrupt
			; and not a function call...
			;
			bra.s	exitInt		; @{"Exit" Link "dos/Exit()"} interrupt...

	If your interrupt will not play with system (OS) structures and your
	own structures are safe to play with you do not need to check for
	the disable.  It is only needed for when the system is in disable but
	that "one last interrupt" still got through.

@{b}   NOTE@{ub}
	This function was not implemented fully until V39.  Due to a mis-cue
	it is not safe to call in V37 EXEC.  (Sorry)

@{b}   INPUTS@{ub}
	A pointer to your interrupt code.  This code is not an EXEC interrupt
	but is dirrectly connected to the hardware interrupt.  Thus, the
	interrupt code must not modify any registers and must return via
	an RTE.

@{b}   RESULTS@{ub}
	The 8-bit vector number used for Zorro-III Quick Interrupts
	If it returns 0, no quick interrupt was allocatable.  The device
	should at this point switch to using the shared interrupt server
	method.

@{b}   SEE ALSO@{ub}

@EndNode

@Node "ObtainSemaphore()" "exec.library/ObtainSemaphore"

@{b}   NAME@{ub}
	ObtainSemaphore -- gain exclusive access to a semaphore

@{b}   SYNOPSIS@{ub}
	ObtainSemaphore(signalSemaphore)
			A0

	void ObtainSemaphore(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *);

@{b}   FUNCTION@{ub}
	@{"Signal" Link "exec/Signal()"} semaphores are used to gain exclusive access to an object.
	ObtainSemaphore is the call used to gain this access.  If another
	user currently has the semaphore locked the call will block until
	the object is available.

	If the current task already has locked the semaphore and attempts to
	lock it again the call will still succeed.  A "nesting count" is
	incremented each time the current owning task of the semaphore calls
	ObtainSemaphore().  This counter is decremented each time
	@{"ReleaseSemaphore()" Link "ReleaseSemaphore()"} is called.  When the counter returns to zero the
	semaphore is actually released, and the next waiting task is called.

	A queue of waiting tasks is maintained on the stacks of the waiting
	tasks.	Each will be called in turn as soon as the current task
	releases the semaphore.

	@{"Signal" Link "exec/Signal()"} Semaphores are different than @{"Procure()/Vacate()" Link "Vacate()"} semaphores.
	The former requires less CPU time, especially if the semaphore is
	not currently locked.  They require very little set up and user
	thought.  The latter flavor of semaphore make no assumptions about
	how they are used -- they are completely general.  Unfortunately
	they are not as efficient as signal semaphores, and require the
	locker to have done some setup before doing the call.

@{b}   INPUT@{ub}
       signalSemaphore -- an initialized signal semaphore structure

@{b}   NOTE@{ub}
	This function preserves all registers (see BUGS).

@{b}   BUGS@{ub}
	Until V37, this function could destroy A0.

@{b}   SEE ALSO@{ub}
	@{"ObtainSemaphoreShared()" Link "ObtainSemaphoreShared()"}, @{"InitSemaphore()" Link "InitSemaphore()"}, @{"ReleaseSemaphore()" Link "ReleaseSemaphore()"},
	@{"AttemptSemaphore()" Link "AttemptSemaphore()"}, @{"ObtainSemaphoreList()" Link "ObtainSemaphoreList()"}, @{"Procure()" Link "Procure()"}, @{"Vacate()" Link "Vacate()"}

@EndNode

@Node "ObtainSemaphoreList()" "exec.library/ObtainSemaphoreList"

@{b}   NAME@{ub}
	ObtainSemaphoreList -- get a list of semaphores.

@{b}   SYNOPSIS@{ub}
	ObtainSemaphoreList(list)
			    A0

	void ObtainSemaphoreList(struct @{"List" Link "INCLUDE:exec/lists.h/Main" 19} *);

@{b}   FUNCTION@{ub}
	@{"Signal" Link "exec/Signal()"} semaphores may be linked together into a list. This function
	takes a list of these semaphores and attempts to lock all of them at
	once. This call is preferable to applying @{"ObtainSemaphore()" Link "ObtainSemaphore()"} to each
	element in the list because it attempts to lock all the elements
	simultaneously, and won't deadlock if someone is attempting to lock
	in some other order.

	This function assumes that only one task at a time will attempt to
	lock the entire list of semaphores.  In other words, there needs to
	be a higher level lock (perhaps another signal semaphore...) that is
	used before someone attempts to lock the semaphore list via
	ObtainSemaphoreList().

	Note that deadlocks may result if this call is used AND someone
	attempts to use @{"ObtainSemaphore()" Link "ObtainSemaphore()"} to lock more than one semaphore on
	the list.  If you wish to lock more than semaphore (but not all of
	them) then you should obtain the higher level lock (see above)

@{b}   INPUT@{ub}
       list -- a list of signal semaphores

@{b}   SEE ALSO@{ub}
	@{"ObtainSemaphoreShared()" Link "ObtainSemaphoreShared()"}, @{"InitSemaphore()" Link "InitSemaphore()"}, @{"ReleaseSemaphore()" Link "ReleaseSemaphore()"},
	@{"AttemptSemaphore()" Link "AttemptSemaphore()"}, @{"ObtainSemaphoreShared()" Link "ObtainSemaphoreShared()"}, @{"Procure()" Link "Procure()"}, @{"Vacate()" Link "Vacate()"}

@EndNode

@Node "ObtainSemaphoreShared()" "exec.library/ObtainSemaphoreShared"

@{b}    NAME@{ub}
	ObtainSemaphoreShared -- gain shared access to a semaphore (V36)

@{b}    SYNOPSIS@{ub}
	ObtainSemaphoreShared(signalSemaphore)
	                      a0

	void ObtainSemaphoreShared(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *);

@{b}    FUNCTION@{ub}
	A lock on a signal semaphore may either be exclusive, or shared.
	Exclusive locks are granted by the @{"ObtainSemaphore()" Link "ObtainSemaphore()"} and
	@{"AttemptSemaphore()" Link "AttemptSemaphore()"} functions.  Shared locks are granted by
	ObtainSemaphoreShared().  Calls may be nested.

	Any number of tasks may simultaneously hold a shared lock on a
	semaphore.  Only one task may hold an exclusive lock.  A typical
	application is a list that is often read, but only occasionally
	written to.

	Any exlusive locker will be held off until all shared lockers
	release the semaphore.  Likewise, if an exlusive lock is held,
	all potential shared lockers will block until the exclusive lock
	is released.  All shared lockers are restarted at the same time.

@{b}    EXAMPLE@{ub}
		ObtainSemaphoreShared(ss);
		/* read data */
		ReleaseSemaohore(ss);

		ObtainSemaphore(ss);
		/* modify data */
		ReleaseSemaohore(ss);

@{b}    NOTES@{ub}
	While this function was added for V36, the feature magically works
	with all older semaphore structures.

	A task owning a shared lock must not attempt to get an exclusive
	lock on the same semaphore.

	Starting in V39, if the caller already has an exclusive lock on the
	semaphore it will return with another nesting of the lock.  Pre-V39
	this would cause a deadlock.  For pre-V39 use, you can use the
	following workaround:

		\* Try to get the shared semaphore *\
		if (!AttemptSemaphoreShared(ss))
		{
			\* Check if we can get the exclusive version *\
			if (!AttemptSemaphore(ss))
			{
				\* Oh well, wait for the shared lock *\
				ObtainSemaphoreShared(ss));
			}
		}
		:
		:
		ReleaseSemaphore(ss);

@{b}    INPUT@{ub}
	signalSemaphore -- an initialized signal semaphore structure

@{b}    NOTE@{ub}
	This call is guaranteed to preserve all registers, starting with
	V37 exec.

@{b}    RESULT@{ub}

@{b}    SEE ALSO@{ub}
	@{"ObtainSemaphore()" Link "ObtainSemaphore()"}, @{"InitSemaphore()" Link "InitSemaphore()"}, @{"ReleaseSemaphore()" Link "ReleaseSemaphore()"},
	@{"AttemptSemaphore()" Link "AttemptSemaphore()"}, @{"ObtainSemaphoreList()" Link "ObtainSemaphoreList()"}, @{"Procure()" Link "Procure()"}, @{"Vacate()" Link "Vacate()"}

@EndNode

@Node "OldOpenLibrary()" "exec.library/OldOpenLibrary"

@{b}   NAME@{ub}
	OldOpenLibrary -- obsolete @{"OpenLibrary" Link "exec/OpenLibrary()"}

@{b}   SYNOPSIS@{ub}
	library = OldOpenLibrary(libName)
	D0			 A1

	struct @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} *OldOpenLibrary(APTR);

@{b}   FUNCTION@{ub}
	The 1.0 release of the Amiga system had an incorrect version of
	@{"OpenLibrary" Link "exec/OpenLibrary()"} that did not check the version number during the
	library open.  This obsolete function is provided so that object
	code compiled using a 1.0 system will still run.

	This exactly the same as "OpenLibrary(libName,0L);"

@{b}   INPUTS@{ub}
	libName - the name of the library to open

@{b}   RESULTS@{ub}
	library - a library pointer for a successful open, else zero

@{b}   SEE ALSO@{ub}
	@{"CloseLibrary" Link "exec/CloseLibrary()"}

@EndNode

@Node "OpenDevice()" "exec.library/OpenDevice"

@{b}   NAME@{ub}
	OpenDevice -- gain access to a device

@{b}   SYNOPSIS@{ub}
	error = OpenDevice(devName, unitNumber, iORequest, flags)
	D0		   A0	    D0		A1	   D1

	@{"BYTE" Link "INCLUDE:exec/types.h/Main" 118} OpenDevice(STRPTR,ULONG,struct @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} *,ULONG);

@{b}   FUNCTION@{ub}
	This function opens the named device/unit and initializes the given
	I/O request block.  Specific documentation on opening procedures
	may come with certain devices.

	The device may exist in memory, or on disk; this is transparent to
	the OpenDevice caller.

	A full path name for the device name is legitimate.  For example
	"test:devs/fred.device".  This allows the use of custom devices
	without requiring the user to copy the device into the system's
	DEVS: directory.

@{b}   NOTES@{ub}
	All calls to OpenDevice should have matching calls to CloseDevice!

	Devices on disk cannot be opened until after DOS has been
	started.

	As of V36 tasks can safely call OpenDevice, though DOS may open
	system requesters (e.g., asking the user to insert the Workbench
	disk if DEVS: is not online).  You must call this function from a
	DOS @{"Process" Link "INCLUDE:dos/dosextens.h/Main" 39} if you want to turn off DOS requesters.

@{b}   INPUTS@{ub}
	devName - requested device name

	unitNumber - the unit number to open on that device.  The format of
		the unit number is device specific.  If the device does
		not have separate units, send a zero.

	iORequest - the I/O request block to be returned with
		appropriate fields initialized.

	flags - additional driver specific information.  This is sometimes
		used to request opening a device with exclusive access.

@{b}   RESULTS@{ub}
	error - Returns a sign-extended copy of the io_Error field
		of the @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16}.  Zero if successful, else an error code
		is returned.

@{b}   BUGS@{ub}
	AmigaDOS file names are not case sensitive, but Exec lists are.  If
	the device name is specified in a different case than it exists on
	disk, unexpected results may occur.  The same holds true if the
	device exists in memory and the device name is specified in
	a different case.

	Prior to V36, tasks could not make OpenDevice calls requiring disk
	access (since tasks are not allowed to make dos.library calls).
	Now OpenDevice is protected from tasks.

@{b}   SEE ALSO@{ub}
	@{"CloseDevice" Link "serial/CloseDevice()"}, @{"DoIO" Link "exec/DoIO()"}, @{"SendIO" Link "exec/SendIO()"}, @{"CheckIO" Link "exec/CheckIO()"}, @{"AbortIO" Link "timer/AbortIO()"}, @{"WaitIO" Link "exec/WaitIO()"}

@EndNode

@Node "OpenLibrary()" "exec.library/OpenLibrary"

@{b}   NAME@{ub}
	OpenLibrary -- gain access to a library

@{b}   SYNOPSIS@{ub}
	library = OpenLibrary(libName, version)
	D0		      A1       D0

	struct @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} *OpenLibrary(STRPTR, ULONG);

@{b}   FUNCTION@{ub}
	This function returns a pointer to a library that was previously
	installed into the system.  If the requested library is exists, and
	if the library version is greater than or equal to the requested
	version, then the open will succeed.

	The library may exist in memory, or on disk; this is transparent to
	the OpenLibrary caller.  Only Processes are allowed to call
	OpenLibrary (since OpenLibrary may in turn call dos.library).

	A full path name for the library name is legitimate.  For example
	"wp:libs/wp.library".  This allows the use of custom libraries
	without requiring the user to copy the library into the system's
	LIBS: directory.

@{b}   NOTES@{ub}
	All calls to OpenLibrary should have matching calls to CloseLibrary!

	Libraries on disk cannot be opened until after DOS has been
	started.

	As of V36 tasks can safely call OpenLibrary, though DOS may open
	system requesters (e.g., asking the user to insert the Workbench
	disk if LIBS: is not online).  You must call this function from a
	DOS @{"Process" Link "INCLUDE:dos/dosextens.h/Main" 39} if you want to turn off DOS requesters.

@{b}   INPUTS@{ub}
	libName - the name of the library to open

	version - the version of the library required.

@{b}   RESULTS@{ub}
	library - a library pointer for a successful open, else zero

@{b}   BUGS@{ub}
	AmigaDOS file names are not case sensitive, but Exec lists are. If
	the library name is specified in a different case than it exists on
	disk, unexpected results may occur.  The same holds true if the
	library exists in memory and the library name is specified in
	a different case.

	Prior to V36, tasks could not make OpenLibrary calls requiring disk
	access (since tasks are not allowed to make dos.library calls).
	Now OpenLibrary is protected from tasks.

	The version number of the resident tag in a disk based library must
	match the version number of the library, or V36 may fail to load it.

@{b}   SEE ALSO@{ub}
	@{"CloseLibrary" Link "exec/CloseLibrary()"}

@EndNode

@Node "OpenResource()" "exec.library/OpenResource"

@{b}   NAME@{ub}
	OpenResource -- gain access to a resource

@{b}   SYNOPSIS@{ub}
	resource = OpenResource(resName)
	D0			A1

	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75} OpenResource(STRPTR);

@{b}   FUNCTION@{ub}
	This function returns a pointer to a resource that was previously
	installed into the system.

	There is no CloseResource() function.

@{b}   INPUTS@{ub}
       resName - the name of the resource requested.

@{b}   RESULTS@{ub}
	resource - if successful, a resource pointer, else @{"NULL" Link "rexxsupport/NULL"}

@EndNode

@Node "Permit()" "exec.library/Permit"

@{b}    NAME@{ub}
	Permit -- permit task rescheduling.

@{b}    SYNOPSIS@{ub}
	Permit()

	void Permit(void);

@{b}    FUNCTION@{ub}
	Allow other tasks to be scheduled to run by the dispatcher, after a
	matching @{"Forbid()" Link "Forbid()"} has been executed.

@{b}    RESULTS@{ub}
	Other tasks will be rescheduled as they are ready to run. In order
	to restore normal task rescheduling, the programmer must execute
	exactly one call to Permit() for every call to @{"Forbid()" Link "Forbid()"}.

@{b}    NOTE@{ub}
	This call is guaranteed to preserve all registers.

@{b}    SEE ALSO@{ub}
	@{"Forbid" Link "exec/Forbid()"}, @{"Disable" Link "exec/Disable()"}, @{"Enable" Link "exec/Enable()"}

@EndNode

@Node "Procure()" "exec.library/Procure"

@{b}   NAME@{ub}
	Procure -- bid for a semaphore                                   (V39)

@{b}   SYNOPSIS@{ub}
	Procure(semaphore, bidMessage)
		A0	    A1

	VOID Procure(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *, struct @{"SemaphoreMessage" Link "INCLUDE:exec/semaphores.h/Main" 50} *);

@{b}   FUNCTION@{ub}
	This function is used to obtain a semaphore in an async manner.
	Like @{"ObtainSemaphore()" Link "ObtainSemaphore()"}, it will obtain a @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} for you
	but unlike @{"ObtainSemaphore()" Link "ObtainSemaphore()"}, you will not block until you get
	the semaphore.  Procure() will just post a request for the semaphore
	and will return.  When the semaphore is available (which could
	be at any time) the bidMessage will @{"ReplyMsg()" Link "ReplyMsg()"} and you will own
	the semaphore.  This lets you wait on multiple semaphores at once
	and to continue processing while waiting for the semaphore.

	NOTE:  Pre-V39, Procure() and @{"Vacate()" Link "Vacate()"} did not work correctly.
	They also did not operate on @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} semaphores.
	Old (and broken) MessageSemaphore use as of V39 will no longer work.

@{b}   INPUT@{ub}
	semaphore - The @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} that you wish to Procure()
	bidMessage- The @{"SemaphoreMessage" Link "INCLUDE:exec/semaphores.h/Main" 50} that you wish replied when
		you obtain access to the semaphore.  The message's
		ssm_Semaphore field will point at the semaphore that
		was obtained.  If the ssm_Semaphore field is @{"NULL" Link "rexxsupport/NULL"},
		the Procure() was aborted via @{"Vacate()" Link "Vacate()"}.
		The mn_ReplyPort field of the message must point to
		a valid message port.
		To obtain a shared semaphore, the ln_Name field
		must be set to 1.  For an exclusive lock, the ln_Name
		field must be 0.  No other values are valid.

@{b}   BUGS@{ub}
	Before V39, Procure() and @{"Vacate()" Link "Vacate()"} used a different semaphore
	system that was very broken.  This new system is only available
	as of V39 even though the LVOs are the same.

@{b}   SEE ALSO@{ub}
	@{"ObtainSemaphoreShared()" Link "ObtainSemaphoreShared()"}, @{"InitSemaphore()" Link "InitSemaphore()"}, @{"ReleaseSemaphore()" Link "ReleaseSemaphore()"},
	@{"AttemptSemaphore()" Link "AttemptSemaphore()"}, @{"ObtainSemaphoreList()" Link "ObtainSemaphoreList()"}, @{"Vacate()" Link "Vacate()"}, @{"ObtainSemaphore()" Link "ObtainSemaphore()"}

@EndNode

@Node "PutMsg()" "exec.library/PutMsg"

@{b}   NAME@{ub}
	PutMsg -- put a message to a message port

@{b}   SYNOPSIS@{ub}
	PutMsg(port, message)
	       A0    A1

	void PutMsg(struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} *, struct @{"Message" Link "INCLUDE:exec/ports.h/Main" 45} *);

@{b}   FUNCTION@{ub}
	This function attaches a message to the end of a given message port.
	It provides a fast, non-copying message sending mechanism.

	Messages can be attached to only one port at a time.  The message
	body can be of any size or form.  Because messages are not copied,
	cooperating tasks share the same message memory.  The sender task
	must not recycle the message until it has been replied by the
	receiver.  Of course this depends on the message handling conventions
	setup by the involved tasks.  If the mn_ReplyPort field is non-zero,
	when the message is replied by the receiver through @{"ReplyMsg()" Link "ReplyMsg()"}, it
	will be sent to that port.

	Any one of the following actions can be set to occur when a message
	is put:

		1. no special action
		2. signal a given task (specified by MP_SIGTASK)
		3. cause a software interrupt (specified by MP_SIGTASK)

	The action is selected depending on the value found in the MP_FLAGS
	of the destination port.

	This function is safe to call from interrupts.

@{b}   IMPLEMENTATION@{ub}
	1.  Sets the mn_Node.ln_Type field of the message to "NT_MESSAGE".
	2.  Attaches the message to the destination port.
	3.  Performs the specified arrival action at the destination.

@{b}   INPUT@{ub}
	port - pointer to a message port
	message - pointer to a message

@{b}   SEE ALSO@{ub}
	@{"GetMsg" Link "exec/GetMsg()"}, @{"ReplyMsg" Link "exec/ReplyMsg()"}, @{"exec/ports.h" Link "INCLUDE:exec/ports.h/Main" 0}

@EndNode

@Node "RawDoFmt()" "exec.library/RawDoFmt"

@{b}   NAME@{ub}
	RawDoFmt -- format data into a character stream.

@{b}   SYNOPSIS@{ub}
	NextData = RawDoFmt(FormatString, DataStream, PutChProc, PutChData);
       d0                  a0            a1          a2         a3

	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75} RawDoFmt(STRPTR,@{"APTR" Link "INCLUDE:exec/types.h/Main" 75},void (*)(),APTR);

@{b}   FUNCTION@{ub}
	perform "C"-language-like formatting of a data stream, outputting
	the result a character at a time.  Where % formatting commands are
	found in the @{"FormatString" Link "locale/FormatString()"}, they will be replaced with the
	corresponding element in the DataStream.  %% must be used in the
	string if a % is desired in the output.

	Under V36, RawDoFmt() returns a pointer to the end of the DataStream
	(The next argument that would have been processed).  This allows
	multiple formatting passes to be made using the same data.

@{b}   INPUTS@{ub}
	@{"FormatString" Link "locale/FormatString()"} - a "C"-language-like @{"NULL" Link "rexxsupport/NULL"} terminated format string,
	with the following supported % options:

	 %[flags][width.limit][length]type

	flags  - only one allowed. '-' specifies left justification.
	width  - field width.  If the first character is a '0', the
		 field will be padded with leading 0's.
	  .    - must follow the field width, if specified
	limit  - maximum number of characters to output from a string.
		 (only valid for %s).
	length - size of input data defaults to WORD for types d, x,
		 and c, 'l' changes this to long (32-bit).
	type   - supported types are:
			b - BSTR, data is 32-bit @{"BPTR" Link "INCLUDE:dos/dos.h/Main" 131} to byte count followed
			    by a byte string, or @{"NULL" Link "rexxsupport/NULL"} terminated byte string.
			    A @{"NULL" Link "rexxsupport/NULL"} @{"BPTR" Link "INCLUDE:dos/dos.h/Main" 131} is treated as an empty string.
			    (Added in V36 exec)
			d - decimal
			u - unsigned decimal (Added in V37 exec)
			x - hexadecimal
			s - string, a 32-bit pointer to a @{"NULL" Link "rexxsupport/NULL"} terminated
			    byte string.  In V36, a @{"NULL" Link "rexxsupport/NULL"} pointer is treated
			    as an empty string
			c - character

	DataStream - a stream of data that is interpreted according to
		 the format string.  Often this is a pointer into
		 the task's stack.
	PutChProc  - the procedure to call with each character to be
		 output, called as:

	PutChProc(Char,  PutChData);
		  D0-0:8 A3

		the procedure is called with a @{"NULL" Link "rexxsupport/NULL"} Char at the end of
		the format string.
		Starting with V45.1, this pointer may be @{"NULL" Link "rexxsupport/NULL"}. In that
		case, the default "stuffChar" procedure shown below is
		used.

	PutChData - a value that is passed through to the PutChProc
		procedure.  This is untouched by RawDoFmt, and may be
		modified by the PutChProc.

@{b}   EXAMPLE@{ub}
	;
	; Simple version of the C "sprintf" function.  Assumes C-style
	; stack-based function conventions.
	;
	;   long eyecount;
	;   eyecount=2;
	;   sprintf(string,"%s have %ld eyes.","Fish",eyecount);
	;
	; would produce "Fish have 2 eyes." in the string buffer.
	;
		XDEF _sprintf
		XREF _AbsExecBase
		XREF _LVORawDoFmt
	_sprintf:	; ( ostring, format, {values} )
		movem.l a2/a3/a6,-(sp)

		move.l	4*4(sp),a3       ;Get the output string pointer
		move.l	5*4(sp),a0       ;Get the @{"FormatString" Link "locale/FormatString()"} pointer
		lea.l	6*4(sp),a1       ;Get the pointer to the DataStream
		lea.l	stuffChar(pc),a2
		move.l	_AbsExecBase,a6
		jsr	_LVORawDoFmt(a6)

		movem.l (sp)+,a2/a3/a6
		rts

	;------ PutChProc function used by RawDoFmt -----------
	stuffChar:
		move.b	d0,(a3)+        ;Put data to output string
		rts

@{b}   WARNING@{ub}
	This Amiga ROM function formats word values in the data stream.  If
	your compiler defaults to longs, you must add an "l" to your
	% specifications.  This can get strange for characters, which might
	look like "%lc".

	The result of RawDoFmt() is *ONLY* valid in V36 and later releases
	of EXEC.  Pre-V36 versions of EXEC have "random" return values.

@{b}   SEE ALSO@{ub}
	Documentation on the C language "printf" call in any C language
	reference book.

@EndNode

@Node "ReleaseSemaphore()" "exec.library/ReleaseSemaphore"

@{b}   NAME@{ub}
	ReleaseSemaphore -- make signal semaphore available to others

@{b}   SYNOPSIS@{ub}
	ReleaseSemaphore(signalSemaphore)
			 A0

	void ReleaseSemaphore(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *);

@{b}   FUNCTION@{ub}
	ReleaseSemaphore() is the inverse of @{"ObtainSemaphore()" Link "ObtainSemaphore()"}. It makes
	the semaphore lockable to other users.	If tasks are waiting for
	the semaphore and this this task is done with the semaphore then
	the next waiting task is signalled.

	Each @{"ObtainSemaphore()" Link "ObtainSemaphore()"} call must be balanced by exactly one
	ReleaseSemaphore() call.  This is because there is a nesting count
	maintained in the semaphore of the number of times that the current
	task has locked the semaphore. The semaphore is not released to
	other tasks until the number of releases matches the number of
	obtains.

	Needless to say, havoc breaks out if the task releases more times
	than it has obtained.

@{b}   INPUT@{ub}
       signalSemaphore -- an initialized signal semaphore structure

@{b}   BUGS@{ub}
	In V39 and V40 Kickstart, there is an error condition that bumps
	ss_NestCount twice, if multiple @{"Procure()" Link "Procure()"} SemaphoreMessages and
	a @{"ObtainSemaphore()" Link "ObtainSemaphore()"} are pending for the same task.

@{b}   NOTE@{ub}
	This call is guaranteed to preserve all registers.

@{b}   SEE ALSO@{ub}
	@{"InitSemaphore()" Link "InitSemaphore()"}, @{"ObtainSemaphore()" Link "ObtainSemaphore()"}, @{"ObtainSemaphoreShared()" Link "ObtainSemaphoreShared()"}

@EndNode

@Node "ReleaseSemaphoreList()" "exec.library/ReleaseSemaphoreList"

@{b}   NAME@{ub}
	ReleaseSemaphoreList -- make a list of semaphores available

@{b}   SYNOPSIS@{ub}
	ReleaseSemaphoreList(list)
			     A0

	void ReleaseSemaphoreList(struct @{"List" Link "INCLUDE:exec/lists.h/Main" 19} *);

@{b}   FUNCTION@{ub}
	ReleaseSemaphoreList() is the inverse of @{"ObtainSemaphoreList()" Link "ObtainSemaphoreList()"}. It
	releases each element in the semaphore list.

	Needless to say, havoc breaks out if the task releases more times
	than it has obtained.

@{b}   INPUT@{ub}
       list -- a list of signal semaphores

@{b}   SEE ALSO@{ub}
	@{"ObtainSemaphoreList()" Link "ObtainSemaphoreList()"}

@EndNode

@Node "RemDevice()" "exec.library/RemDevice"

@{b}   NAME@{ub}
	RemDevice -- remove a device from the system

@{b}   SYNOPSIS@{ub}
	RemDevice(device)
	          A1

	void RemDevice(struct @{"Device" Link "INCLUDE:exec/devices.h/Main" 23} *);

@{b}   FUNCTION@{ub}
	This function calls the device's EXPUNGE vector, which requests
	that a device delete itself.  The device may refuse to do this if
	it is busy or currently open. This is not typically called by user
	code.

	There are certain, limited circumstances where it may be
	appropriate to attempt to specifically flush a certain device.
	Example:

	 /* Attempts to flush the named device out of memory. */
	 #include @{"<exec/types.h>" Link "INCLUDE:exec/types.h/Main" 0}
	 #include @{"<exec/execbase.h>" Link "INCLUDE:exec/execbase.h/Main" 0}

	 void FlushDevice(name)
	 @{"STRPTR" Link "INCLUDE:exec/types.h/Main" 137} name;
	 {
	 struct @{"Device" Link "INCLUDE:exec/devices.h/Main" 23} *result;

	    Forbid();
	    result = (struct @{"Device" Link "INCLUDE:exec/devices.h/Main" 23} *)FindName(&SysBase->DeviceList, name);
	    if (result != NULL)
	         RemDevice(result);
	    Permit();
	 }

@{b}   INPUTS@{ub}
	device - pointer to a device node

@{b}   SEE ALSO@{ub}
	@{"AddLibrary" Link "exec/AddLibrary()"}

@EndNode

@Node "RemHead()" "exec.library/RemHead"

@{b}   NAME@{ub}
	RemHead -- remove the head node from a list

@{b}   SYNOPSIS@{ub}
	node = RemHead(list)
	D0	       A0

	struct @{"Node" Link "INCLUDE:exec/nodes.h/Main" 21} *RemHead(struct @{"List" Link "INCLUDE:exec/lists.h/Main" 19} *);

@{b}   FUNCTION@{ub}
	Get a pointer to the head node and remove it from the list.
	Assembly programmers may prefer to use the REMHEAD macro from
	"exec/lists.i".

@{b}   WARNING@{ub}
	This function does not arbitrate for access to the list.  The
	calling task must be the owner of the involved list.

@{b}   INPUTS@{ub}
	list - a pointer to the target list header

@{b}   RESULT@{ub}
	node - the node removed or zero when empty list

@{b}   SEE ALSO@{ub}
	@{"AddHead" Link "exec/AddHead()"}, @{"AddTail" Link "exec/AddTail()"}, @{"Enqueue" Link "exec/Enqueue()"}, @{"Insert" Link "exec/Insert()"}, @{"Remove" Link "exec/Remove()"}, @{"RemTail" Link "exec/RemTail()"}

@EndNode

@Node "RemIntServer()" "exec.library/RemIntServer"

@{b}   NAME@{ub}
	RemIntServer -- remove an interrupt server from a server chain

@{b}   SYNOPSIS@{ub}
	RemIntServer(intNum, interrupt)
		     D0      A1

	void RemIntServer(ULONG,struct @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} *);

@{b}   FUNCTION@{ub}
	This function removes an interrupt server node from the given
	server chain.

	If this server was the last one on this chain, interrupts for this
	chain are disabled.

@{b}   INPUTS@{ub}
	intNum - the Paula interrupt bit (0..14)
	interrupt - pointer to an interrupt server node

@{b}   BUGS@{ub}
	Before V36 Kickstart, the feature that disables the interrupt
	would not function.  For most server chains this does not
	cause a problem.

@{b}   SEE ALSO@{ub}
	@{"AddIntServer" Link "exec/AddIntServer()"}, @{"hardware/intbits.h" Link "INCLUDE:hardware/intbits.h/Main" 0}

@EndNode

@Node "RemLibrary()" "exec.library/RemLibrary"

@{b}   NAME@{ub}
	RemLibrary -- remove a library from the system

@{b}   SYNOPSIS@{ub}
	RemLibrary(library)
	           A1

	void RemLibrary(struct @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} *);

@{b}   FUNCTION@{ub}
	This function calls the library's EXPUNGE vector, which requests
	that a library delete itself.  The library may refuse to do this if
	it is busy or currently open. This is not typically called by user
	code.

	There are certain, limited circumstances where it may be
	appropriate to attempt to specifically flush a certain @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32}.
	Example:

	 /* Attempts to flush the named library out of memory. */
	 #include @{"<exec/types.h>" Link "INCLUDE:exec/types.h/Main" 0}
	 #include @{"<exec/execbase.h>" Link "INCLUDE:exec/execbase.h/Main" 0}

	 void FlushLibrary(name)
	 @{"STRPTR" Link "INCLUDE:exec/types.h/Main" 137} name;
	 {
	 struct @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} *result;

	    Forbid();
	    result = (struct @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} *)FindName(&SysBase->LibList, name);
	    if (result != NULL)
	         RemLibrary(result);
	    Permit();
	 }

@{b}   INPUTS@{ub}
	library - pointer to a library node structure

@EndNode

@Node "RemMemHandler()" "exec.library/RemMemHandler"

@{b}   NAME@{ub}
	RemMemHandler - @{"Remove" Link "exec/Remove()"} low memory handler from exec              (V39)

@{b}   SYNOPSIS@{ub}
	RemMemHandler(memHandler)
	              A1

	VOID RemMemHandler(struct @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} *);

@{b}   FUNCTION@{ub}
	This function removes the low memory handler from the system.
	This function can be called from within a handler.  If removing
	oneself, it is important that the handler returns MEM_ALL_DONE.

@{b}   NOTE@{ub}
	When removing a handler, the handler may be called until this
	function returns.  Thus, the handler must still be valid until
	then.

@{b}   INPUTS@{ub}
	memHandler - Pointer to a handler added with @{"AddMemHandler()" Link "AddMemHandler()"}

@{b}   SEE ALSO@{ub}
	@{"AddMemHandler" Link "exec/AddMemHandler()"}, exec/interrupts.i

@EndNode

@Node "Remove()" "exec.library/Remove"

@{b}   NAME@{ub}
	Remove -- remove a node from a list

@{b}   SYNOPSIS@{ub}
	Remove(node)
	       A1

	void Remove(struct @{"Node" Link "INCLUDE:exec/nodes.h/Main" 21} *);

@{b}   FUNCTION@{ub}
	Unlink a node from whatever list it is in.  Nodes that are not part
	of a list must not be passed to this function!  Assembly programmers
	may prefer to use the REMOVE macro from "exec/lists.i".

@{b}   WARNING@{ub}
	This function does not arbitrate for access to the list.  The
	calling task must be the owner of the involved list.

@{b}   INPUTS@{ub}
	node - the node to remove

@{b}   SEE ALSO@{ub}
	@{"AddHead" Link "exec/AddHead()"}, @{"AddTail" Link "exec/AddTail()"}, @{"Enqueue" Link "exec/Enqueue()"}, @{"Insert" Link "exec/Insert()"}, @{"RemHead" Link "exec/RemHead()"}, @{"RemTail" Link "exec/RemTail()"}

@EndNode

@Node "RemPort()" "exec.library/RemPort"

@{b}   NAME@{ub}
	RemPort -- remove a message port from the system

@{b}   SYNOPSIS@{ub}
	RemPort(port)
		A1

	void RemPort(struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} *);

@{b}   FUNCTION@{ub}
	This function removes a message port structure from the system's
	message port list.  Subsequent attempts to rendezvous by name with
	this port will fail.

@{b}   INPUTS@{ub}
	port - pointer to a message port

@{b}   SEE ALSO@{ub}
	@{"AddPort" Link "exec/AddPort()"}, @{"FindPort" Link "exec/FindPort()"}

@EndNode

@Node "RemResource()" "exec.library/RemResource"

@{b}   NAME@{ub}
	RemResource -- remove a resource from the system

@{b}   SYNOPSIS@{ub}
	RemResource(resource)
		   A1

	void RemResource(APTR);

@{b}   FUNCTION@{ub}
	This function removes an existing resource from the system resource
	list.  There must be no outstanding users of the resource.

@{b}   INPUTS@{ub}
	resource - pointer to a resource node

@{b}   SEE ALSO@{ub}
	@{"AddResource" Link "exec/AddResource()"}

@EndNode

@Node "RemSemaphore()" "exec.library/RemSemaphore"

@{b}   NAME@{ub}
	RemSemaphore -- remove a signal semaphore from the system

@{b}   SYNOPSIS@{ub}
	RemSemaphore(signalSemaphore)
		     A1

	void RemSemaphore(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *);

@{b}   FUNCTION@{ub}
	This function removes a signal semaphore structure from the
	system's signal semaphore list.  Subsequent attempts to
	rendezvous by name with this semaphore will fail.

@{b}   INPUTS@{ub}
       signalSemaphore -- an initialized signal semaphore structure

@{b}   SEE ALSO@{ub}
	@{"AddSemaphore" Link "exec/AddSemaphore()"}, @{"FindSemaphore" Link "exec/FindSemaphore()"}


@EndNode

@Node "RemTail()" "exec.library/RemTail"

@{b}   NAME@{ub}
	RemTail -- remove the tail node from a list

@{b}   SYNOPSIS@{ub}
	node = RemTail(list)
	D0	       A0

	struct @{"Node" Link "INCLUDE:exec/nodes.h/Main" 21} *RemTail(struct @{"List" Link "INCLUDE:exec/lists.h/Main" 19} *);

@{b}   FUNCTION@{ub}
	@{"Remove" Link "exec/Remove()"} the last node from a list, and return a pointer to it. If
	the list is empty, return zero. Assembly programmers may prefer to
	use the REMTAIL macro from "exec/lists.i".

@{b}   WARNING@{ub}
	This function does not arbitrate for access to the list.  The
	calling task must be the owner of the involved list.

@{b}   INPUTS@{ub}
	list - a pointer to the target list header

@{b}   RESULT@{ub}
	node - the node removed or zero when empty list

@{b}   SEE ALSO@{ub}
	@{"AddHead" Link "exec/AddHead()"}, @{"AddTail" Link "exec/AddTail()"}, @{"Enqueue" Link "exec/Enqueue()"}, @{"Insert" Link "exec/Insert()"}, @{"Remove" Link "exec/Remove()"}, @{"RemHead" Link "exec/RemHead()"}, RemTail

@EndNode

@Node "RemTask()" "exec.library/RemTask"

@{b}   NAME@{ub}
	RemTask -- remove a task from the system

@{b}   SYNOPSIS@{ub}
	RemTask(task)
		A1

	void RemTask(struct @{"Task" Link "INCLUDE:exec/tasks.h/Main" 23} *);

@{b}   FUNCTION@{ub}
	This function removes a task from the system.  Deallocation of
	resources should have been performed prior to calling this
	function.  Removing some other task is very dangerous.	Generally
	is is best to arrange for tasks to call RemTask(0L) on themselves.

	RemTask will automagically free any memory lists attached to the
	task's tc_MemEntry list.

@{b}   INPUTS@{ub}
	task - pointer to the task node representing the task to be
	       removed.  A zero value indicates self removal, and will
	       cause the next ready task to begin execution.

@{b}   BUGS@{ub}
	Before V36 if RemTask() was called on a task other than the current
	task, and that task was created with @{"amiga.lib/CreateTask" Link "amiga_lib/CreateTask()"}, there was
	a slight chance of a crash.  The problem can be hidden by bracketing
	RemTask() with @{"Forbid()/Permit()" Link "Permit()"}.

@{b}   SEE ALSO@{ub}
	@{"AddTask" Link "exec/AddTask()"}, @{"exec/AllocEntry" Link "exec/AllocEntry()"}, @{"amiga.lib/DeleteTask" Link "amiga_lib/DeleteTask()"}

@EndNode

@Node "ReplyMsg()" "exec.library/ReplyMsg"

@{b}   NAME@{ub}
	ReplyMsg -- put a message to its reply port

@{b}   SYNOPSIS@{ub}
	ReplyMsg(message)
		 A1

	void ReplyMsg(struct @{"Message" Link "INCLUDE:exec/ports.h/Main" 45} *);

@{b}   FUNCTION@{ub}
	This function sends a message to its reply port.  This is usually
	done when the receiver of a message has finished and wants to
	return it to the sender (so that it can be re-used or deallocated,
	whatever).

	This call may be made from interrupts.

@{b}   INPUT@{ub}
	message - a pointer to the message

@{b}   IMPLEMENTATION@{ub}
	1. Places "NT_REPLYMSG" into the mn_Node.ln_Type field.
	2. Puts the message to the port specified by mn_ReplyPort.
	   If mn_ReplyPort is @{"NULL" Link "rexxsupport/NULL"}, sets mn_Node.ln_Type to "NT_FREEMSG"
	   (use this feature only with extreme care).

@{b}   SEE ALSO@{ub}
	@{"GetMsg" Link "exec/GetMsg()"}, @{"PutMsg" Link "exec/PutMsg()"}, @{"exec/ports.h" Link "INCLUDE:exec/ports.h/Main" 0}

@EndNode

@Node "SendIO()" "exec.library/SendIO"

@{b}   NAME@{ub}
	SendIO -- initiate an I/O command

@{b}   SYNOPSIS@{ub}
	SendIO(iORequest)
	       A1

	void SendIO(struct @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} *);

@{b}   FUNCTION@{ub}
	This function requests the device driver start processing the given
	I/O request.  The device will return control without waiting for
	the I/O to complete.

	The io_Flags field of the @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} will be set to zero before the
	request is sent.  See @{"BeginIO()" Link "serial/BeginIO()"} for more details.

@{b}   INPUTS@{ub}
	iORequest - pointer to an I/O request, or a device specific
		    extended @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16}.

@{b}   SEE ALSO@{ub}
	@{"DoIO" Link "exec/DoIO()"}, @{"CheckIO" Link "exec/CheckIO()"}, @{"WaitIO" Link "exec/WaitIO()"}, @{"AbortIO" Link "timer/AbortIO()"}

@EndNode

@Node "SetExcept()" "exec.library/SetExcept"

@{b}   NAME@{ub}
	SetExcept -- define certain signals to cause exceptions

@{b}   SYNOPSIS@{ub}
	oldSignals = SetExcept(newSignals, signalMask)
	D0		       D0	   D1

	ULONG SetExcept(ULONG,ULONG);

@{b}   FUNCTION@{ub}
	This function defines which of the task's signals will cause a
	private task exception.  When any of the signals occurs the task's
	exception handler will be dispatched.  If the signal occurred prior
	to calling SetExcept, the exception will happen immediately.

	The user function pointed to by the task's tc_ExceptCode gets
	called as:

	    newExcptSet = <exceptCode>(signals, exceptData),SysBase
	    D0			       D0	A1	    A6

	    signals - The set of signals that caused this exception.  These
		Signals have been disabled from the current set of signals
		that can cause an exception.

	    exceptData - A copy of the task structure tc_ExceptData field.

	    newExcptSet - The set of signals in NewExceptSet will be re-
		enabled for exception generation.  Usually this will be the
		same as the Signals that caused the exception.

@{b}   INPUTS@{ub}
	newSignals - the new values for the signals specified in
		signalMask.
	signalMask - the set of signals to be effected

@{b}   RESULTS@{ub}
	oldSignals - the prior exception signals

@{b}   EXAMPLE@{ub}
	Get the current state of all exception signals:
	    SetExcept(0,0)
	Change a few exception signals:
	    SetExcept($1374,$1074)

@{b}   SEE ALSO@{ub}
	@{"Signal" Link "exec/Signal()"}, @{"SetSignal" Link "exec/SetSignal()"}

@EndNode

@Node "SetFunction()" "exec.library/SetFunction"

@{b}   NAME@{ub}
	SetFunction -- change a function vector in a library

@{b}   SYNOPSIS@{ub}
	oldFunc = SetFunction(library, funcOffset, funcEntry)
	D0		      A1       A0.W	   D0

	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75} SetFunction(struct @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} *,@{"LONG" Link "INCLUDE:exec/types.h/Main" 112},APTR);

@{b}   FUNCTION@{ub}
	SetFunction is a functional way of changing where vectors in a
	library point.	They are changed in such a way that the
	checksumming process will never falsely declare a library to be
	invalid.

@{b}   WARNING@{ub}
	If you use SetFunction on a function that can be called from
	interrupts, you are obligated to provide your own arbitration.

@{b}   NOTE@{ub}
	SetFunction cannot be used on non-standard libraries like pre-V36
	dos.library.  Here you must manually @{"Forbid()" Link "Forbid()"}, preserve all 6
	original bytes, set the new vector, @{"SumLibrary()" Link "SumLibrary()"}, then @{"Permit()" Link "Permit()"}.

@{b}   INPUTS@{ub}
	library    - a pointer to the library to be changed
	funcOffset - the offset of the function to be replaced
	funcEntry  - pointer to new function

@{b}   RESULTS@{ub}
	oldFunc    - pointer to the old function that was just replaced

@EndNode

@Node "SetIntVector()" "exec.library/SetIntVector"

@{b}   NAME@{ub}
	SetIntVector -- set a new handler for a system interrupt vector

@{b}   SYNOPSIS@{ub}
	oldInterrupt = SetIntVector(intNumber, interrupt)
	D0			    D0         A1

	struct @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} *SetIntVector(ULONG, struct @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} *);

@{b}   FUNCTION@{ub}
	This function provides a mechanism for setting the system interrupt
	vectors.  These are non-sharable; setting a new interrupt handler
	disconnects the old one.  Installed handlers are responsible for
	processing, enabling and clearing the interrupt.  Note that interrupts
	may have been left in any state by the previous code.

	The IS_CODE and IS_DATA pointers of the @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} structure will
	be copied into a private place by Exec.  A pointer to the previously
	installed @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} structure is returned.

	When the system calls the specified interrupt code, the registers are
	setup as follows:

	    D0 - scratch
	    D1 - scratch (on entry: active
			  interrupts -> equals INTENA & INTREQ)

	    A0 - scratch (on entry: pointer to base of custom chips
			  for fast indexing)
	    A1 - scratch (on entry: Interrupt's IS_DATA pointer)

	    A5 - jump vector register (scratch on call)
	    A6 - Exec library base pointer (scratch on call)

	    all other registers must be preserved

@{b}   INPUTS@{ub}
	intNum - the Paula interrupt bit number (0..14).  Only non-chained
		 interrupts should be set.  Use @{"AddIntServer()" Link "AddIntServer()"} for server
		 chains.
	interrupt - a pointer to an @{"Interrupt" Link "INCLUDE:exec/interrupts.h/Main" 20} structure containing the
		 handler's entry point and data segment pointer.  A @{"NULL" Link "rexxsupport/NULL"}
		 interrupt pointer will remove the current interrupt and
		 set illegal values for IS_CODE and IS_DATA.

		 By convention, the LN_NAME of the interrupt structure must
		 point a descriptive string so that other users may
		 identify who currently has control of the interrupt.

@{b}   RESULT@{ub}
	A pointer to the prior interrupt structure which had control
	of this interrupt.

@{b}   SEE ALSO@{ub}
	@{"AddIntServer()" Link "AddIntServer()"},exec/interrupts.i,hardware/intbits.i

@EndNode

@Node "SetSignal()" "exec.library/SetSignal"

@{b}   NAME@{ub}
	SetSignal -- define the state of this task's signals

@{b}   SYNOPSIS@{ub}
	oldSignals = SetSignal(newSignals, signalMask)
	D0		       D0	   D1

	ULONG SetSignal(ULONG,ULONG);

@{b}   FUNCTION@{ub}
	This function can query or modify the state of the current task's
	received signal mask.  Setting the state of signals is considered
	dangerous.  Reading the state of signals is safe.

@{b}   INPUTS@{ub}
	newSignals - the new values for the signals specified in
		     signalSet.
	signalMask - the set of signals to be affected.

@{b}   RESULTS@{ub}
	oldSignals - the prior values for all signals

@{b}   EXAMPLES@{ub}
	Get the current state of all signals:
	    SetSignal(0L, 0L);
	Clear the CTRL-C signal:
	    SetSignal(0L, SIGBREAKF_CTRL_C);


	Check if the CTRL-C signal was pressed:

	    #include @{"<dos/dos.h>" Link "INCLUDE:dos/dos.h/Main" 0}

	    /* Check & clear CTRL_C signal */
	    if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
	        printf("CTRL-C pressed!\n");

@{b}   SEE ALSO@{ub}
	@{"Signal" Link "exec/Signal()"}, @{"Wait" Link "exec/Wait()"}

@EndNode

@Node "SetSR()" "exec.library/SetSR"

@{b}   NAME@{ub}
	SetSR -- get and/or set processor status register

@{b}   SYNOPSIS@{ub}
	oldSR = SetSR(newSR, mask)
	D0	      D0     D1

	ULONG SetSR(ULONG, ULONG);

@{b}   FUNCTION@{ub}
	This function provides a means of modifying the CPU status register
	in a "safe" way (well, how safe can a function like this be
	anyway?).  This function will only affect the status register bits
	specified in the mask parameter.  The prior content of the entire
	status register is returned.

@{b}   INPUTS@{ub}
	newSR - new values for bits specified in the mask.
	    All other bits are not effected.
	mask - bits to be changed

@{b}   RESULTS@{ub}
	oldSR - the entire status register before new bits

@{b}   EXAMPLES@{ub}
	To get the current SR:
	    currentSR = SetSR(0,0);
	To change the processor interrupt level to 3:
	    oldSR = SetSR($0300,$0700);
	Set processor interrupts back to prior level:
	    SetSR(oldSR,$0700);

@EndNode

@Node "SetTaskPri()" "exec.library/SetTaskPri"

@{b}   NAME@{ub}
	SetTaskPri -- get and set the priority of a task

@{b}   SYNOPSIS@{ub}
	oldPriority = SetTaskPri(task, priority)
	D0-0:8			 A1    D0-0:8

	@{"BYTE" Link "INCLUDE:exec/types.h/Main" 118} SetTaskPri(struct @{"Task" Link "INCLUDE:exec/tasks.h/Main" 23} *,BYTE);

@{b}   FUNCTION@{ub}
	This function changes the priority of a task regardless of its
	state.	The old priority of the task is returned.  A reschedule is
	performed, and a context switch may result.

	To change the priority of the currently running task, pass the
	result of FindTask(0); as the task pointer.

@{b}   INPUTS@{ub}
	task - task to be affected
	priority - the new priority for the task

@{b}   RESULT@{ub}
	oldPriority - the tasks previous priority

@EndNode

@Node "Signal()" "exec.library/Signal"

@{b}   NAME@{ub}
	Signal -- signal a task

@{b}   SYNOPSIS@{ub}
	Signal(task, signals)
	       A1    D0

	void Signal(struct @{"Task" Link "INCLUDE:exec/tasks.h/Main" 23} *,ULONG);

@{b}   FUNCTION@{ub}
	This function signals a task with the given signals.  If the task
	is currently waiting for one or more of these signals, it will be
	made ready and a reschedule will occur. If the task is not waiting
	for any of these signals, the signals will be posted to the task
	for possible later use. A signal may be sent to a task regardless
	of whether it is running, ready, or waiting.

	This function is considered "low level".  Its main purpose is to
	support multiple higher level functions like @{"PutMsg" Link "exec/PutMsg()"}.

	This function is safe to call from interrupts.

@{b}   INPUT@{ub}
	task - the task to be signalled
	signals - the signals to be sent

@{b}   SEE ALSO@{ub}
	@{"Wait" Link "exec/Wait()"}, @{"SetSignal" Link "exec/SetSignal()"}

@EndNode

@Node "StackSwap()" "exec.library/StackSwap"

@{b}   NAME@{ub}
	StackSwap - EXEC supported method of replacing task's stack      (V37)

@{b}   SYNOPSIS@{ub}
	StackSwap(newStack)
	          A0

	VOID StackSwap(struct @{"StackSwapStruct" Link "INCLUDE:exec/tasks.h/Main" 51} *);

@{b}   FUNCTION@{ub}
	This function will, in an EXEC supported manner, swap the
	stack of your task with the given values in StackSwap.
	The @{"StackSwapStruct" Link "INCLUDE:exec/tasks.h/Main" 51} structure will then contain the values
	of the old stack such that the old stack can be restored.
	This function is new in V37.

@{b}   NOTE@{ub}
	If you do a stack swap, only the new stack is set up.
	This function does not copy the stack or do anything else
	other than set up the new stack for the task.  It is
	generally required that you restore your stack before
	exiting.

@{b}   INPUTS@{ub}
	newStack - A structure that contains the values for the
		new upper and lower stack bounds and the new stack
		pointer.  This structure will have its values
		replaced by those in you task such that you can
		restore the stack later.

@{b}   RESULTS@{ub}
	newStack - The structure will now contain the old stack.
		This means that StackSwap(foo); StackSwap(foo);
		will effectively do nothing.

@{b}   SEE ALSO@{ub}
	@{"AddTask" Link "exec/AddTask()"}, @{"RemTask" Link "exec/RemTask()"}, @{"exec/tasks.h" Link "INCLUDE:exec/tasks.h/Main" 0}

@EndNode

@Node "SumKickData()" "exec.library/SumKickData"

@{b}   NAME@{ub}
	SumKickData -- compute the checksum for the Kickstart delta list

@{b}   SYNOPSIS@{ub}
	checksum = SumKickData()
	D0

	ULONG SumKickData(void);

@{b}   FUNCTION@{ub}
	The Amiga system has some ROM (or Kickstart) resident code that
	provides the basic functions for the machine.  This code is
	unchangeable by the system software.  This function is part of a
	support system to modify parts of the ROM.

	The ROM code is linked together at run time via ROMTags (also known
	as @{"Resident" Link "INCLUDE:exec/resident.h/Main" 16} structures, defined in @{"exec/resident.h)" Link "INCLUDE:exec/resident.h/Main" 0}.  These tags tell
	Exec's low level boot code what subsystems exist in which regions of
	memory.  The current list of ROMTags is contained in the ResModules
	field of @{"ExecBase" Link "INCLUDE:exec/execbase.h/Main" 32}.  By default this list contains any ROMTags found
	in the address ranges $F80000-$FFFFFF and $F00000-$F7FFFF.

	There is also a facility to selectively add or replace modules to the
	ROMTag list.  These modules can exist in RAM, and the memory they
	occupy will be deleted from the memory free list during the boot
	process.  SumKickData() plays an important role in this run-time
	modification of the ROMTag array.

	Three variables in @{"ExecBase" Link "INCLUDE:exec/execbase.h/Main" 32} are used in changing the ROMTag array:
	KickMemPtr, KickTagPtr, and KickCheckSum. KickMemPtr points to a
	linked list of @{"MemEntry" Link "INCLUDE:exec/memory.h/Main" 38} structures. The memory that these @{"MemEntry" Link "INCLUDE:exec/memory.h/Main" 38}
	structures reference will be allocated (via AllocAbs) at boot time.
	The @{"MemEntry" Link "INCLUDE:exec/memory.h/Main" 38} structure itself must also be in the list.

	KickTagPtr points to a long-word array of the same format as the
	ResModules array.  The array has a series of pointers to ROMTag
	structures.  The array is either @{"NULL" Link "rexxsupport/NULL"} terminated, or will have an
	entry with the most significant bit (bit 31) set.  The most
	significant bit being set says that this is a link to another
	long-word array of ROMTag entries.  This new array's address can be
	found by clearing bit 31.

	KickCheckSum has the result of SumKickData().  It is the checksum of
	both the KickMemPtr structure and the KickTagPtr arrays.  If the
	checksum does not compute correctly then both KickMemPtr and
	KickTagPtr will be ignored.

	If all the memory referenced by KickMemPtr can't be allocated then
	KickTagPtr will be ignored.

	There is one more important caveat about adding ROMTags. All this
	ROMTag magic is run very early on in the system -- before expansion
	memory is added to the system. Therefore any memory in this
	additional ROMTag area must be addressable at this time. This means
	that your ROMTag code, @{"MemEntry" Link "INCLUDE:exec/memory.h/Main" 38} structures, and resident arrays
	cannot be in expansion memory.  There are two regions of memory that
	are acceptable:  one is chip memory, and the other is "Ranger" memory
	(memory in the range between $C00000-$D80000).

	@{"Remember" Link "INCLUDE:intuition/intuition.h/Main" 1503} that changing an existing ROMTag entry falls into the
	"heavy magic" category -- be very careful when doing it.  The odd are
	that you will blow yourself out of the water.

@{b}   NOTE@{ub}
	SumKickData was introduced in the 1.2 release

@{b}   RESULT@{ub}
	Value to be stuffed into ExecBase->KickCheckSum.

@{b}   WARNING@{ub}
	After writing to KickCheckSum, you should push the data cache.
	This prevents potential problems with large copyback style caches.
	A call to @{"CacheClearU" Link "exec/CacheClearU()"} will do fine.

@{b}   SEE ALSO@{ub}
	@{"InitResident" Link "exec/InitResident()"}, @{"FindResident" Link "exec/FindResident()"}

@EndNode

@Node "SumLibrary()" "exec.library/SumLibrary"

@{b}   NAME@{ub}
	SumLibrary -- compute and check the checksum on a library

@{b}   SYNOPSIS@{ub}
	SumLibrary(library)
		   A1

	void SumLibrary(struct @{"Library" Link "INCLUDE:exec/libraries.h/Main" 32} *);

@{b}   FUNCTION@{ub}
	SumLibrary computes a new checksum on a library.  It can also be
	used to check an old checksum.	If an old checksum does not match,
	and the library has not been marked as changed, then the system
	will call @{"Alert()" Link "Alert()"}.

	This call could also be periodically made by some future
	system-checking task.

@{b}   INPUTS@{ub}
	library - a pointer to the library to be changed

@{b}   NOTE@{ub}
	An alert will occur if the checksum fails.

@{b}   SEE ALSO@{ub}
	@{"SetFunction" Link "exec/SetFunction()"}

@EndNode

@Node "SuperState()" "exec.library/SuperState"

@{b}   NAME@{ub}
	SuperState -- enter supervisor state with user stack

@{b}   SYNOPSIS@{ub}
	oldSysStack = SuperState()
	D0

	@{"APTR" Link "INCLUDE:exec/types.h/Main" 75} SuperState(void);

@{b}   FUNCTION@{ub}
	Enter supervisor mode while running on the user's stack. The user
	still has access to user stack variables.  Be careful though, the
	user stack must be large enough to accommodate space for all
	interrupt data -- this includes all possible nesting of interrupts.
	This function does nothing when called from supervisor state.

@{b}   RESULTS@{ub}
	oldSysStack - system stack pointer; save this.	It will come in
		      handy when you return to user state.  If the system
		      is already in supervisor mode, oldSysStack is zero.

@{b}   SEE ALSO@{ub}
	@{"UserState/Supervisor" Link "exec/Supervisor()"}


@EndNode

@Node "Supervisor()" "exec.library/Supervisor"

@{b}   NAME@{ub}
	Supervisor -- trap to a short supervisor mode function

@{b}   SYNOPSIS@{ub}
	result = Supervisor(userFunc)
	Rx                   A5

	ULONG Supervisor(void *);

@{b}   FUNCTION@{ub}
	Allow a normal user-mode program to execute a short assembly language
	function in the supervisor mode of the processor.  Supervisor() does
	not modify or save registers; the user function has full access to the
	register set.   All rules that apply to interrupt code must be
	followed.  In addition, no system calls are permitted.  The function
	must end with an RTE instruction.

@{b}   EXAMPLE@{ub}
		;Obtain the Exception Vector base.  68010 or greater only!
		MOVECtrap:	movec.l	VBR,d0	;$4e7a,$0801
				rte

@{b}   INPUTS@{ub}
	userFunc - A pointer to a short assembly language function ending
		   in RTE.  The function has full access to the register set.

@{b}   RESULTS@{ub}
	result   - Whatever values the userFunc left in the registers.

@{b}   SEE ALSO@{ub}
	@{"SuperState" Link "exec/SuperState()"},@{"UserState" Link "exec/UserState()"}

@EndNode

@Node "TypeOfMem()" "exec.library/TypeOfMem"

@{b}   NAME@{ub}
	TypeOfMem -- determine attributes of a given memory address

@{b}   SYNOPSIS@{ub}
	attributes = TypeOfMem(address)
	D0		       A1

	ULONG TypeOfMem(void *);

@{b}   FUNCTION@{ub}
	Given a RAM memory address, search the system memory lists and
	return its memory attributes.  The memory attributes are similar to
	those specified when the memory was first allocated: (eg. MEMF_CHIP
	and MEMF_FAST).

	This function is usually used to determine if a particular block of
	memory is within CHIP space.

	If the address is not in known-space, a zero will be returned.
	(Anything that is not RAM, like the ROM or expansion area, will
	return zero.  Also the first few bytes of a memory area are used up
	by the MemHeader.)

@{b}   INPUT@{ub}
	address - a memory address

@{b}   RESULT@{ub}
	attributes - a long word of memory attribute flags.
	If the address is not in known RAM, zero is returned.

@{b}   SEE ALSO@{ub}
	@{"AllocMem()" Link "AllocMem()"}

@EndNode

@Node "UserState()" "exec.library/UserState"

@{b}   NAME@{ub}
	UserState -- return to user state with user stack

@{b}   SYNOPSIS@{ub}
	UserState(sysStack)
		  D0

	void UserState(APTR);

@{b}   FUNCTION@{ub}
	Return to user state with user stack, from supervisor state with
	user stack.  This function is normally used in conjunction with the
	@{"SuperState" Link "exec/SuperState()"} function above.

	This function must not be called from the user state.

@{b}   INPUT@{ub}
	sysStack - supervisor stack pointer

@{b}   BUGS@{ub}
	This function is broken in V33/34 Kickstart.  Fixed in V1.31 setpatch.

@{b}   SEE ALSO@{ub}
	@{"SuperState/Supervisor" Link "exec/Supervisor()"}

@EndNode

@Node "Vacate()" "exec.library/Vacate"

@{b}   NAME@{ub}
	Vacate -- release a bitMessage from @{"Procure()" Link "Procure()"}                    (V39)

@{b}   SYNOPSIS@{ub}
	Vacate(semaphore, bidMessage)
	       A0         A1

	void Vacate(struct @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} *,struct @{"SemaphoreMessage" Link "INCLUDE:exec/semaphores.h/Main" 50} *);

@{b}   FUNCTION@{ub}
	This function can be used to release a semaphore obtained via
	@{"Procure()" Link "Procure()"}.  However, the main purpose for this call is to be
	able to remove a bid for a semaphore that has not yet responded.
	This is required when a @{"Procure()" Link "Procure()"} was issued and the program
	no longer needs to get the semaphore and wishes to cancel the
	@{"Procure()" Link "Procure()"} request.  The canceled request will be replied with
	the ssm_Semaphore field set to @{"NULL" Link "rexxsupport/NULL"}.  If you own the semaphore,
	the message was already replied and only the ssm_Semaphore field
	will be cleared.

	NOTE:  Pre-V39, @{"Procure()" Link "Procure()"} and Vacate() did not work correctly.
	They also did not operate on @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} semaphores.
	Old (and broken) MessageSemaphore use as of V39 will no longer work.

@{b}   INPUT@{ub}
	semaphore - The @{"SignalSemaphore" Link "INCLUDE:exec/semaphores.h/Main" 39} that you wish to Vacate()
	bidMessage- The @{"SemaphoreMessage" Link "INCLUDE:exec/semaphores.h/Main" 50} that you wish to abort.
		The message's ssm_Semaphore field will be cleared.
		The message will be replied if it is still on the waiting
		list.  If it is not on the waiting list, it is assumed
		that the semaphore is owned and it will be released.

@{b}   BUGS@{ub}
	Before V39, @{"Procure()" Link "Procure()"} and Vacate() used a different semaphore
	system that was very broken.  This new system is only available
	as of V39 even though the LVOs are the same.

@{b}   SEE ALSO@{ub}
	@{"ObtainSemaphoreShared()" Link "ObtainSemaphoreShared()"}, @{"InitSemaphore()" Link "InitSemaphore()"}, @{"ReleaseSemaphore()" Link "ReleaseSemaphore()"},
	@{"AttemptSemaphore()" Link "AttemptSemaphore()"}, @{"ObtainSemaphoreList()" Link "ObtainSemaphoreList()"}, @{"Procure()" Link "Procure()"}, @{"ObtainSemaphore()" Link "ObtainSemaphore()"}

@EndNode

@Node "Wait()" "exec.library/Wait"

@{b}   NAME@{ub}
	Wait -- wait for one or more signals

@{b}   SYNOPSIS@{ub}
	signals = Wait(signalSet)
	D0	       D0

	ULONG Wait(ULONG);

@{b}   FUNCTION@{ub}
	This function will cause the current task to suspend waiting for
	one or more signals.  When one or more of the specified signals
	occurs, the task will return to the ready state, and those signals
	will be cleared.

	If a signal occurred prior to calling Wait(), the wait condition will
	be immediately satisfied, and the task will continue to run without
	delay.

@{b}   CAUTION@{ub}
	This function cannot be called while in supervisor mode or
	interrupts!  This function will break the action of a @{"Forbid()" Link "Forbid()"} or
	@{"Disable()" Link "Disable()"} call.

@{b}   INPUT@{ub}
	signalSet - The set of signals for which to wait.
		    Each bit represents a particular signal.

@{b}   RESULTS@{ub}
	signals - the set of signals that were active

@EndNode

@Node "WaitIO()" "exec.library/WaitIO"

@{b}   NAME@{ub}
	WaitIO -- wait for completion of an I/O request

@{b}   SYNOPSIS@{ub}
	error = WaitIO(iORequest)
	D0	       A1

	@{"BYTE" Link "INCLUDE:exec/types.h/Main" 118} WaitIO(struct @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} *);

@{b}   FUNCTION@{ub}
	This function waits for the specified I/O request to complete, then
	removes it from the replyport.	If the I/O has already completed,
	this function will return immediately.

	This function should be used with care, as it does not return until
	the I/O request completes; if the I/O never completes, this
	function will never return, and your task will hang.  If this
	situation is a possibility, it is safer to use the @{"Wait()" Link "Wait()"} function.
	@{"Wait()" Link "Wait()"} will return return when any of a specified set of signal is
	received.  This is how I/O timeouts can be properly handled.

@{b}   WARNING@{ub}
	If this @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} was "Quick" or otherwise finished BEFORE this
	call, this function drops though immediately, with no call to
	@{"Wait()" Link "Wait()"}.  A side effect is that the signal bit related the port may
	remain set.  Expect this.

	When removing a known complete @{"IORequest" Link "INCLUDE:exec/io.h/Main" 16} from a port, WaitIO() is the
	preferred method.  A simple @{"Remove()" Link "Remove()"} would require a
	@{"Disable()/Enable()" Link "Enable()"} pair!

@{b}   INPUTS@{ub}
	iORequest - pointer to an I/O request block

@{b}   RESULTS@{ub}
	error - zero if successful, else an error is returned
		(a sign extended copy of io_Error).

@{b}   SEE ALSO@{ub}
	@{"DoIO" Link "exec/DoIO()"}, @{"SendIO" Link "exec/SendIO()"}, @{"CheckIO" Link "exec/CheckIO()"}, @{"AbortIO" Link "timer/AbortIO()"}

@EndNode

@Node "WaitPort()" "exec.library/WaitPort"

@{b}   NAME@{ub}
	WaitPort -- wait for a given port to be non-empty

@{b}   SYNOPSIS@{ub}
	message = WaitPort(port)
	D0		   A0

	struct @{"Message" Link "INCLUDE:exec/ports.h/Main" 45} *WaitPort(struct @{"MsgPort" Link "INCLUDE:exec/ports.h/Main" 26} *);

@{b}   FUNCTION@{ub}
	This function waits for the given port to become non-empty.  If
	necessary, the @{"Wait()" Link "Wait()"} function will be called to wait for the port
	signal.  If a message is already present at the port, this function
	will return immediately.  The return value is always a pointer to
	the first message queued (but it is not removed from the queue).

@{b}   CAUTION@{ub}
	More than one message may be at the port when this returns.  It is
	proper to call the @{"GetMsg()" Link "GetMsg()"} function in a loop until all messages
	have been handled, then wait for more to arrive.

	To wait for more than one port, combine the signal bits from each
	port into one call to the @{"Wait()" Link "Wait()"} function, then use a @{"GetMsg()" Link "GetMsg()"} loop
	to collect any and all messages.  It is possible to get a signal
	for a port WITHOUT a message showing up.  Plan for this.

	WaitPort() can only be used with message ports whose mp_Flags
	port arrival action is PA_SIGNAL and if the calling task is the
	same as given in the mp_SigTask field.

@{b}   INPUT@{ub}
	port - a pointer to the message port

@{b}   RETURN@{ub}
	message - a pointer to the first available message

@{b}   SEE ALSO@{ub}
	@{"GetMsg" Link "exec/GetMsg()"}

@EndNode

