@DATABASE "exec.guide"
@AUTHOR AmiS <amis@amiga.org.ru> © 1998-2002
@INDEX ".Index.guide/Main"
@WORDWRAP
@$VER: exec.library 40.10 autodocs 1.3
@HELP help

@NODE Help "Copyright 1998-2002 AmiS"
 @{fg shine}exec.library 40.10@{fg text}  Version 1.3
 This is a NewStyle Autodocs for Amiga Developer Community.

 Designed 1999-2002 by @{fg shine}AmiS@{fg text}
 Send your bug report to @{fg fill}amis@amiga.org.ru@{fg text}

@ENDNODE

@NODE Main "exec.library"
@PREV Main
@{jcenter}@{b} A @{ub}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}A@{ub}@{lindent 4}
@{lindent 35}@{" AbortIO()                " LINK "AbortIO"}  - attempt to abort an in-progress I/O request@{lindent 4}
@{lindent 35}@{" AddDevice()              " LINK "AddDevice"}  - add a device to the system@{lindent 4}
@{lindent 35}@{" AddHead()                " LINK "AddHead"}  - insert node at the head of a list@{lindent 4}
@{lindent 35}@{" AddIntServer()           " LINK "AddIntServer"}  - add an interrupt server to a system server chain@{lindent 4}
@{lindent 35}@{" AddLibrary()             " LINK "AddLibrary"}  - add a library to the system@{lindent 4}
@{lindent 35}@{" AddMemHandler()          " LINK "AddMemHandler"}  - add a low memory handler to exec  @{FG SHINE}(V39)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" AddMemList()             " LINK "AddMemList"}  - add memory to the system free pool@{lindent 4}
@{lindent 35}@{" AddPort()                " LINK "AddPort"}  - add a public message port to the system@{lindent 4}
@{lindent 35}@{" AddResource()            " LINK "AddResource"}  - add a resource to the system@{lindent 4}
@{lindent 35}@{" AddSemaphore()           " LINK "AddSemaphore"}  - initialize then add a signal semaphore to the system@{lindent 4}
@{lindent 35}@{" AddTail()                " LINK "AddTail"}  - append node to tail of a list@{lindent 4}
@{lindent 35}@{" AddTask()                " LINK "AddTask"}  - add a task to the system@{lindent 4}
@{lindent 35}@{" Alert()                  " LINK "Alert"}  - alert the user of an error@{lindent 4}
@{lindent 35}@{" AllocAbs()               " LINK "AllocAbs"}  - allocate at a given location@{lindent 4}
@{lindent 35}@{" Allocate()               " LINK "Allocate"}  - allocate a block of memory@{lindent 4}
@{lindent 35}@{" AllocEntry()             " LINK "AllocEntry"}  - allocate many regions of memory@{lindent 4}
@{lindent 35}@{" AllocMem()               " LINK "AllocMem"}  - allocate memory given certain requirements@{lindent 4}
@{lindent 35}@{" AllocPooled()            " LINK "AllocPooled"}  - allocate memory with the pool manager  @{FG SHINE}(V39)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" AllocSignal()            " LINK "AllocSignal"}  - allocate a signal bit@{lindent 4}
@{lindent 35}@{" AllocTrap()              " LINK "AllocTrap"}  - allocate a processor trap vector@{lindent 4}
@{lindent 35}@{" AllocVec()               " LINK "AllocVec"}  - allocate memory and keep track of the size  @{FG SHINE}(V36)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" AttemptSemaphore()       " LINK "AttemptSemaphore"}  - try to obtain without blocking@{lindent 4}
@{lindent 35}@{" AttemptSemaphoreShared() " LINK "AttemptSemaphoreShared"}  - try to obtain without blocking  @{FG SHINE}(V37)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" AvailMem()               " LINK "AvailMem"}  - memory available given certain requirements
@ENDNODE

@NODE MainC "exec.library"
@{jcenter}@{" A " LINK Main 0}@{b} C @{ub}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}C@{ub}@{lindent 4}
@{lindent 35}@{" CacheClearE()            " LINK "CacheClearE"}  - cache clearing with extended control  @{FG SHINE}(V37)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" CacheClearU()            " LINK "CacheClearU"}  - user callable simple cache clearing  @{FG SHINE}(V37)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" CacheControl()           " LINK "CacheControl"}  - instruction & data cache control@{lindent 4}
@{lindent 35}@{" CachePostDMA()           " LINK "CachePostDMA"}  - take actions after to hardware DMA  @{FG SHINE}(V37)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" CachePreDMA()            " LINK "CachePreDMA"}  - take actions prior to hardware DMA  @{FG SHINE}(V37)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" Cause()                  " LINK "Cause"}  - cause a software interrupt@{lindent 4}
@{lindent 35}@{" CheckIO()                " LINK "CheckIO"}  - get the status of an IORequest@{lindent 4}
@{lindent 35}@{" CloseDevice()            " LINK "CloseDevice"}  - conclude access to a device@{lindent 4}
@{lindent 35}@{" CloseLibrary()           " LINK "CloseLibrary"}  - conclude access to a library@{lindent 4}
@{lindent 35}@{" ColdReboot()             " LINK "ColdReboot"}  - reboot the Amiga  @{FG SHINE}(V36)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" CopyMem()                " LINK "CopyMem"}  - general purpose memory copy function@{lindent 4}
@{lindent 35}@{" CopyMemQuick()           " LINK "CopyMemQuick"}  - optimized memory copy function@{lindent 4}
@{lindent 35}@{" CreateIORequest()        " LINK "CreateIORequest"}  - create an IORequest structure  @{FG SHINE}(V36)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" CreateMsgPort()          " LINK "CreateMsgPort"}  - allocate and initialize a new message port  @{FG SHINE}(V36)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" CreatePool()             " LINK "CreatePool"}  - generate a private memory pool header @{FG SHINE}(V39)@{FG TEXT}
@ENDNODE

@NODE MainD "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{b} D @{ub}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}D@{ub}@{lindent 4}
@{lindent 35}@{" Deallocate()             " LINK "Deallocate"}  - deallocate a block of memory@{lindent 4}
@{lindent 35}@{" Debug()                  " LINK "Debug"}  - run the system debugger@{lindent 4}
@{lindent 35}@{" DeleteIORequest()        " LINK "DeleteIORequest"}  - free a request made by @{fg fill}CreateIORequest()@{fg text}  @{FG SHINE}(V36)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" DeleteMsgPort()          " LINK "DeleteMsgPort"}  - free a message port created by @{fg fill}CreateMsgPort()@{fg text}  @{FG SHINE}(V36)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" DeletePool()             " LINK "DeletePool"}  - drain an entire memory pool  @{FG SHINE}(V39)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" Disable()                " LINK "Disable"}  - disable interrupt processing@{lindent 4}
@{lindent 35}@{" DoIO()                   " LINK "DoIO"}  - perform an I/O command and wait for completion
@ENDNODE

@NODE MainE "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{b} E @{ub}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}E@{ub}@{lindent 4}
@{lindent 35}@{" Enable()                 " LINK "Enable"}  - permit system interrupts to resume@{lindent 4}
@{lindent 35}@{" Enqueue()                " LINK "Enqueue"}  - insert or append node to a system queue
@ENDNODE

@NODE MainF "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{b} F @{ub}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}F@{ub}@{lindent 4}
@{lindent 35}@{" FindName()               " LINK "FindName"}  - find a system list node with a given name@{lindent 4}
@{lindent 35}@{" FindPort()               " LINK "FindPort"}  - find a given system message port@{lindent 4}
@{lindent 35}@{" FindResident()           " LINK "FindResident"}  - find a resident module by name@{lindent 4}
@{lindent 35}@{" FindSemaphore()          " LINK "FindSemaphore"}  - find a given system signal semaphore@{lindent 4}
@{lindent 35}@{" FindTask()               " LINK "FindTask"}  - find a task with the given name or find oneself@{lindent 4}
@{lindent 35}@{" Forbid()                 " LINK "Forbid"}  - forbid task rescheduling@{lindent 4}
@{lindent 35}@{" FreeEntry()              " LINK "FreeEntry"}  - free many regions of memory@{lindent 4}
@{lindent 35}@{" FreeMem()                " LINK "FreeMem"}  - deallocate with knowledge@{lindent 4}
@{lindent 35}@{" FreePooled()             " LINK "FreePooled"}  - free pooled memory  @{FG SHINE}(V39)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" FreeSignal()             " LINK "FreeSignal"}  - free a signal bit@{lindent 4}
@{lindent 35}@{" FreeTrap()               " LINK "FreeTrap"}  - free a processor trap@{lindent 4}
@{lindent 35}@{" FreeVec()                " LINK "FreeVec"}  - return @{fg fill}AllocVec()@{fg text} memory to the system  @{FG SHINE}(V36)@{FG TEXT}
@ENDNODE

@NODE MainG "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{b} G @{ub}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}G@{ub}@{lindent 4}
@{lindent 35}@{" GetCC()                  " LINK "GetCC"}  - get condition codes in a 68010 compatible way@{lindent 4}
@{lindent 35}@{" GetMsg()                 " LINK "GetMsg"}  - get next message from a message port
@ENDNODE

@NODE MainI "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{b} I @{ub}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}I@{ub}@{lindent 4}
@{lindent 35}@{" InitCode()               " LINK "InitCode"}  - initialize resident code modules (internal function)@{lindent 4}
@{lindent 35}@{" InitResident()           " LINK "InitResident"}  - initialize resident module@{lindent 4}
@{lindent 35}@{" InitSemaphore()          " LINK "InitSemaphore"}  - initialize a signal semaphore@{lindent 4}
@{lindent 35}@{" InitStruct()             " LINK "InitStruct"}  - initialize memory from a table@{lindent 4}
@{lindent 35}@{" Insert()                 " LINK "Insert"}  - insert a node into a list
@ENDNODE

@NODE MainM "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{b} M @{ub}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}M@{ub}@{lindent 4}
@{lindent 35}@{" MakeFunctions()          " LINK "MakeFunctions"}  - construct a function jump table@{lindent 4}
@{lindent 35}@{" MakeLibrary()            " LINK "MakeLibrary"}  - construct a library
@ENDNODE

@NODE MainO "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{b} O @{ub}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}O@{ub}@{lindent 4}
@{lindent 35}@{" ObtainQuickVector()      " LINK "ObtainQuickVector"}  - obtain an install a Quick Interrupt vector  @{FG SHINE}(V39)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" ObtainSemaphore()        " LINK "ObtainSemaphore"}  - gain exclusive access to a semaphore@{lindent 4}
@{lindent 35}@{" ObtainSemaphoreList()    " LINK "ObtainSemaphoreList"}  - get a list of semaphores@{lindent 4}
@{lindent 35}@{" ObtainSemaphoreShared()  " LINK "ObtainSemaphoreShared"}  - gain shared access to a semaphore  @{FG SHINE}(V36)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" OldOpenLibrary()         " LINK "OldOpenLibrary"}  - obsolete @{fg fill}OpenLibrary()@{fg text}@{lindent 4}
@{lindent 35}@{" OpenDevice()             " LINK "OpenDevice"}  - gain access to a device@{lindent 4}
@{lindent 35}@{" OpenLibrary()            " LINK "OpenLibrary"}  - gain access to a library@{lindent 4}
@{lindent 35}@{" OpenResource()           " LINK "OpenResource"}  - gain access to a resource
@ENDNODE

@NODE MainP "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{b} P @{ub}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}P@{ub}@{lindent 4}
@{lindent 35}@{" Permit()                 " LINK "Permit"}  - permit task rescheduling@{lindent 4}
@{lindent 35}@{" Procure()                " LINK "Procure"}  - bid for a semaphore  @{FG SHINE}(V39)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" PutMsg()                 " LINK "PutMsg"}  - put a message to a message port
@ENDNODE

@NODE MainR "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{b} R @{ub}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}R@{ub}@{lindent 4}
@{lindent 35}@{" RawDoFmt()               " LINK "RawDoFmt"}  - format data into a character stream@{lindent 4}
@{lindent 35}@{" ReleaseSemaphore()       " LINK "ReleaseSemaphore"}  - make signal semaphore available to others@{lindent 4}
@{lindent 35}@{" ReleaseSemaphoreList()   " LINK "ReleaseSemaphoreList"}  - make a list of semaphores available@{lindent 4}
@{lindent 35}@{" RemDevice()              " LINK "RemDevice"}  - remove a device from the system@{lindent 4}
@{lindent 35}@{" RemHead()                " LINK "RemHead"}  - remove the head node from a list@{lindent 4}
@{lindent 35}@{" RemIntServer()           " LINK "RemIntServer"}  - remove an interrupt server from a server chain@{lindent 4}
@{lindent 35}@{" RemLibrary()             " LINK "RemLibrary"}  - remove a library from the system@{lindent 4}
@{lindent 35}@{" RemMemHandler()          " LINK "RemMemHandler"}  - remove low memory handler from exec  @{FG SHINE}(V39)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" Remove()                 " LINK "Remove"}  - remove a node from a list@{lindent 4}
@{lindent 35}@{" RemPort()                " LINK "RemPort"}  - remove a message port from the system@{lindent 4}
@{lindent 35}@{" RemResource()            " LINK "RemResource"}  - remove a resource from the system@{lindent 4}
@{lindent 35}@{" RemSemaphore()           " LINK "RemSemaphore"}  - remove a signal semaphore from the system@{lindent 4}
@{lindent 35}@{" RemTail()                " LINK "RemTail"}  - remove the tail node from a list@{lindent 4}
@{lindent 35}@{" RemTask()                " LINK "RemTask"}  - remove a task from the system@{lindent 4}
@{lindent 35}@{" ReplyMsg()               " LINK "ReplyMsg"}  - put a message to its reply port
@ENDNODE

@NODE MainS "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{b} S @{ub}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}S@{ub}@{lindent 4}
@{lindent 35}@{" SendIO()                 " LINK "SendIO"}  - initiate an I/O command@{lindent 4}
@{lindent 35}@{" SetExcept()              " LINK "SetExcept"}  - define certain signals to cause exceptions@{lindent 4}
@{lindent 35}@{" SetFunction()            " LINK "SetFunction"}  - change a function vector in a library@{lindent 4}
@{lindent 35}@{" SetIntVector()           " LINK "SetIntVector"}  - set a new handler for a system interrupt vector@{lindent 4}
@{lindent 35}@{" SetSignal()              " LINK "SetSignal"}  - define the state of this task's signals@{lindent 4}
@{lindent 35}@{" SetSR()                  " LINK "SetSR"}  - get and/or set processor status register@{lindent 4}
@{lindent 35}@{" SetTaskPri()             " LINK "SetTaskPri"}  - get and set the priority of a task@{lindent 4}
@{lindent 35}@{" Signal()                 " LINK "Signal"}  - signal a task@{lindent 4}
@{lindent 35}@{" StackSwap()              " LINK "StackSwap"}  - EXEC supported method of replacing task's stack  @{FG SHINE}(V37)@{FG TEXT}@{lindent 4}
@{lindent 35}@{" SumKickData()            " LINK "SumKickData"}  - compute the checksum for the Kickstart delta list@{lindent 4}
@{lindent 35}@{" SumLibrary()             " LINK "SumLibrary"}  - compute and check the checksum on a library@{lindent 4}
@{lindent 35}@{" SuperState()             " LINK "SuperState"}  - enter supervisor state with user stack@{lindent 4}
@{lindent 35}@{" Supervisor()             " LINK "Supervisor"}  - trap to a short supervisor mode function
@ENDNODE

@NODE MainT "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{b} T @{ub}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}T@{ub}@{lindent 4}
@{lindent 35}@{" TypeOfMem()              " LINK "TypeOfMem"}  - determine attributes of a given memory address
@ENDNODE

@NODE MainU "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{b} U @{ub}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}U@{ub}@{lindent 4}
@{lindent 35}@{" UserState()              " LINK "UserState"}  - return to user state with user stack
@ENDNODE

@NODE MainV "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{b} V @{ub}@{" W " LINK MainW 0}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}V@{ub}@{lindent 4}
@{lindent 35}@{" Vacate()                 " LINK "Vacate"}  - release a bitMessage from @{fg fill}Procure()@{fg text}  @{FG SHINE}(V39)@{FG TEXT}
@ENDNODE

@NODE MainW "exec.library"
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{b} W @{ub}@{" SAD " LINK MainSAD 0}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{jleft}@{lindent 1}
@{b}W@{ub}@{lindent 4}
@{lindent 35}@{" Wait()                   " LINK "Wait"}  - wait for one or more signals@{lindent 4}
@{lindent 35}@{" WaitIO()                 " LINK "WaitIO"}  - wait for completion of an I/O request@{lindent 4}
@{lindent 35}@{" WaitPort()               " LINK "WaitPort"}  - wait for a given port to be non-empty
@ENDNODE

@NODE MainSAD "exec.library"
@NEXT MainSAD
@{jcenter}@{" A " LINK Main 0}@{" C " LINK MainC 0}@{" D " LINK MainD 0}@{" E " LINK MainE 0}@{" F " LINK MainF 0}@{" G " LINK MainG 0}@{" I " LINK MainI 0}@{" M " LINK MainM 0}@{" O " LINK MainO 0}@{" P " LINK MainP 0}@{" R " LINK MainR 0}@{" S " LINK MainS 0}@{" T " LINK MainT 0}@{" U " LINK MainU 0}@{" V " LINK MainV 0}@{" W " LINK MainW 0}@{b} SAD @{ub}
@{jcenter}
@{u}@{b}Exec.library@{uu}@{ub}
@{lindent 1}@{jcenter}
@{u}@{b}Simple Amiga Debugging Kernel (SAD)@{uu}@{ub}
@{jleft}@{lindent 4}
@{lindent 28}@{" --Overview--      " LINK "--Overview--"}  - it is in EXEC starting in @{FG SHINE}V39@{FG TEXT}@{lindent 4}

@{lindent 28}@{" ALLOCATE_MEMORY   " LINK "ALLOCATE_MEMORY"}  - allocate a chunk of memory@{lindent 4}
@{lindent 28}@{" CALL_ADDRESS      " LINK "CALL_ADDRESS"}  - JSR to the given address@{lindent 4}
@{lindent 28}@{" FREE_MEMORY       " LINK "FREE_MEMORY"}  - free the memory allocated with the ALLOCATE MEMORY command@{lindent 4}
@{lindent 28}@{" GET_CONTEXT_FRAME " LINK "GET_CONTEXT_FRAME"}  - return a pointer to the saved context@{lindent 4}
@{lindent 28}@{" NOP               " LINK "NOP"}  - do nothing other than tell SAD you are still there@{lindent 4}
@{lindent 28}@{" READ_ARRAY        " LINK "READ_ARRAY"}  - read a range of bytes@{lindent 4}
@{lindent 28}@{" READ_BYTE         " LINK "READ_BYTE"}  - read a byte from the given address@{lindent 4}
@{lindent 28}@{" READ_LONG         " LINK "READ_LONG"}  - read a long from the given address@{lindent 4}
@{lindent 28}@{" READ_WORD         " LINK "READ_WORD"}  - read a word from the given address  @{FG SHINE}(V40 SAD)@{FG TEXT}@{lindent 4}
@{lindent 28}@{" RESET             " LINK "RESET"}  - reset the computer@{lindent 4}
@{lindent 28}@{" RETURN_TO_SYSTEM  " LINK "RETURN_TO_SYSTEM"}  - return to system@{lindent 4}
@{lindent 28}@{" TURN_OFF_SINGLE   " LINK "TURN_OFF_SINGLE"}  - turn off SAD single stepping mode@{lindent 4}
@{lindent 28}@{" TURN_ON_SINGLE    " LINK "TURN_ON_SINGLE"}  - turn on SAD single stepping mode@{lindent 4}
@{lindent 28}@{" WRITE_ARRAY       " LINK "WRITE_ARRAY"}  - write a range of bytes@{lindent 4}
@{lindent 28}@{" WRITE_BYTE        " LINK "WRITE_BYTE"}  - write the given data to the address given  @{FG SHINE}(V40 SAD)@{FG TEXT}@{lindent 4}
@{lindent 28}@{" WRITE_LONG        " LINK "WRITE_LONG"}  - write the given data to the address given@{lindent 4}
@{lindent 28}@{" WRITE_WORD        " LINK "WRITE_WORD"}  - write the given data to the address given@{lindent 4}
@ENDNODE

@NODE "AbortIO" "exec.library/AbortIO()"
@PREV AbortIO
@{jcenter}
@{u}@{b}AbortIO()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{lindent 8}@{ub}@{fg text}
AbortIO - attempt to abort an in-progress I/O request
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{lindent 8}@{ub}@{fg text}
AbortIO(iORequest)
           A1

VOID AbortIO(struct @{"IORequest" LINK "include:exec/io.h/MAIN" 17} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{lindent 8}@{ub}@{fg text}
Ask a device to abort a previously started @{"IORequest" LINK "include:exec/io.h/MAIN" 17}. This is done by calling the device's ABORTIO vector, with your given @{"IORequest" LINK "include:exec/io.h/MAIN" 17}.

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" 17}, and reply to it earlier than it would otherwise have done.
@{lindent 4}
@{fg shine}@{b}NOTE@{lindent 8}@{ub}@{fg text}
AbortIO() does NOT @{"Remove()" LINK "Remove" 0} the @{"IORequest" LINK "include:exec/io.h/MAIN" 17} 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.
@{lindent 4}
@{fg shine}@{b}EXAMPLE@{lindent 8}@{ub}@{fg text}
AbortIO(timer_request);
@{"WaitIO" LINK "WaitIO" 0}(timer_request);
/* Message is free to be reused */
@{lindent 4}
@{fg shine}@{b}INPUTS@{lindent 8}@{ub}@{fg text}
@{lindent 20}iORequest - pointer to an I/O request block (must have been used at least once.  May be active or finished).
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{lindent 8}@{ub}@{fg text}
@{"WaitIO()" LINK "WaitIO" 0}, @{"DoIO()" LINK "DoIO" 0}, @{"SendIO()" LINK "SendIO" 0}, @{"CheckIO()" LINK "CheckIO" 0}
@ENDNODE

@NODE "AddDevice" "exec.library/AddDevice()"
@{jcenter}
@{u}@{b}AddDevice()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{lindent 8}@{ub}@{fg text}
AddDevice - add a device to the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{lindent 8}@{ub}@{fg text}
AddDevice(device)
          A1

void AddDevice(struct @{"Device" LINK "include:exec/devices.h/MAIN" 23} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{lindent 8}@{ub}@{fg text}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{lindent 8}@{ub}@{fg text}
device - pointer to a properly initialized device node
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{lindent 8}@{ub}@{fg text}
@{"RemDevice()" LINK "RemDevice" 0}, @{"OpenDevice()" LINK "OpenDevice" 0}, @{"CloseDevice()" LINK "CloseDevice" 0}, @{"MakeLibrary()" LINK "MakeLibrary" 0}
@ENDNODE

@NODE "AddHead" "exec.library/AddHead()"
@{jcenter}
@{u}@{b}AddHead()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{lindent 8}@{ub}@{fg text}
AddHead - insert node at the head of a list
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{lindent 8}@{ub}@{fg text}
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} *)
@{lindent 4}
@{fg shine}@{b}FUNCTION@{lindent 8}@{ub}@{fg text}
Add a node to the head of a doubly linked list. Assembly programmers may prefer to use the ADDHEAD macro from @{"exec/lists.h" LINK "include:exec/lists.h" 0}.
@{lindent 4}
@{fg shine}@{b}WARNING@{lindent 8}@{ub}@{fg text}
This function does not arbitrate for access to the list. The calling task must be the owner of the involved list.
@{lindent 4}
@{fg shine}@{b}INPUTS@{lindent 8}@{ub}@{fg text}
list - a pointer to the target list header
node - the node to insert at head
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{lindent 8}@{ub}@{fg text}
@{"AddTail()" LINK "AddTail" 0}, @{"Enqueue()" LINK "Enqueue" 0}, @{"Insert()" LINK "Insert" 0}, @{"Remove()" LINK "Remove" 0}, @{"RemHead()" LINK "RemHead" 0}, @{"RemTail()" LINK "RemTail" 0}
@ENDNODE

@NODE "AddIntServer" "exec.library/AddIntServer()"
@{jcenter}
@{u}@{b}AddIntServer()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{lindent 8}@{ub}@{fg text}
AddIntServer - add an interrupt server to a system server chain
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{lindent 8}@{ub}@{fg text}
AddIntServer(intNum, interrupt)
             D0-0:4  A1

void AddIntServer(ULONG, struct @{"Interrupt" LINK "include:exec/interrupts.h/MAIN" 21} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{lindent 8}@{ub}@{fg text}
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:
@{lindent 12}
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
@{lindent 4}
@{fg shine}@{b}INPUTS@{lindent 8}@{ub}@{fg text}
@{lindent 17}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.@{lindent 8}
@{lindent 20}interrupt - pointer to an Interrupt 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.
@{lindent 4}
@{fg shine}@{b}WARNING@{lindent 8}@{ub}@{fg text}
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).
@{lindent 4}
@{fg shine}@{b}BUGS@{lindent 8}@{ub}@{fg text}
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).
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{lindent 8}@{ub}@{fg text}
@{"RemIntServer()" LINK "RemIntServer" 0}, @{"SetIntVector()" LINK "SetIntVector" 0}, @{"hardware/intbits.h" LINK "include:hardware/intbits.h" 0}, @{"exec/interrupts.h" LINK "include:exec/interrupts.h" 0}
@ENDNODE

@NODE "AddLibrary" "exec.library/AddLibrary()"
@{jcenter}
@{u}@{b}AddLibrary()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AddLibrary - add a library to the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
AddLibrary(library)
           A1

void AddLibrary(struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
library - pointer to a properly initialized library structure
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"RemLibrary()" LINK "RemLibrary" 0}, @{"CloseLibrary()" LINK "CloseLibrary" 0}, @{"OpenLibrary()" LINK "OpenLibrary" 0}, @{"MakeLibrary()" LINK "MakeLibrary" 0}
@ENDNODE

@NODE "AddMemHandler" "exec.library/AddMemHandler()"
@{jcenter}
@{u}@{b}AddMemHandler()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AddMemHandler - Add a low memory handler to exec  @{FG SHINE}(V39)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
AddMemHandler(memHandler)
              A1

VOID AddMemHandler(struct @{"Interrupt" LINK "include:exec/interrupts.h/MAIN" 21} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This function adds a low memory handler to the system. The handler is described in the Interrupt 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)
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}EXAMPLE@{ub}@{fg text}@{lindent 8}
struct @{"Interrupt" LINK "include:exec/interrupts.h/MAIN" 21} *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" 89}
                ; in a0, the value of is_Data in a1 and
                ; @{"ExecBase" LINK "include:exec/execbase.h/MAIN" 33} 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...
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 21}memHandler - A pointer to a completely filled in Interrupt 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)
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"RemMemHandler()" LINK "RemMemHandler" 0}, @{"exec/interrupts.h" LINK "include:exec/interrupst.h" 0}
@ENDNODE

@NODE "AddMemList" "exec.library/AddMemList()"
@{jcenter}
@{u}@{b}AddMemList()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AddMemList - add memory to the system free pool
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
AddMemList( size, attributes, pri, base, name )
            D0    D1          D2   A0    A1

void AddMemList(ULONG, ULONG, LONG, APTR, STRPTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 27} structure. The remainder will be made available to the rest of the world.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 15}size - the size (in bytes) of the memory area@{lindent 8}
@{lindent 21}attributes - the attributes word that the memory pool will have@{lindent 8}
@{lindent 15}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.@{lindent 8}
@{lindent 15}base - the base of the new memory area@{lindent 8}
@{lindent 15}name - the name that will be used in the memory header, or 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.
@{lindent 4}
@{fg shine}@{b}NOTES@{ub}@{fg text}@{lindent 8}
*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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AllocMem()" LINK "AllocMem" 0}, @{"exec/memory.h" LINK "include:exec/memory.h/MAIN" 0}
@ENDNODE

@NODE "AddPort" "exec.library/AddPort()"
@{jcenter}
@{u}@{b}AddPort()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AddPort - add a public message port to the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
AddPort(port)
        A1

void AddPort(struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
 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" 0} 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" 0} 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()" LINK "RemPort" 0}) before deallocating its memory.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
 A point of confusion is that clearing a @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} 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 for the @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} must be initialized. This is automatically handled by AddPort(), and amiga.lib/CreatePort. This initialization can be done manually with @{"amiga.lib/NewList()" LINK "amiga_lib.guide/NewList" 0} or the assembly NEWLIST macro.

 Do not AddPort an active port.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
port - pointer to a message port
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"RemPort()" LINK "RemPort" 0}, @{"FindPort()" LINK "FindPort" 0}, @{"amiga.lib/CreatePort()" LINK "amiga_lib.guide/CreatePort" 0}, @{"amiga.lib/NewList()" LINK "amiga_lib.guide/NewList" 0}
@ENDNODE

@NODE "AddResource" "exec.library/AddResource()"
@{jcenter}
@{u}@{b}AddResource()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AddResource - add a resource to the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
AddResource(resource)
            A1

void AddResource(APTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 node (LIB_SIZE).
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
resource - pointer an initialized resource node
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"RemResource()" LINK "RemResource" 0}, @{"OpenResource()" LINK "OpenResource" 0}, @{"MakeLibrary()" LINK "MakeLibrary" 0}
@ENDNODE

@NODE "AddSemaphore" "exec.library/AddSemaphore()"
@{jcenter}
@{u}@{b}AddSemaphore()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AddSemaphore - initialize then add a signal semaphore to the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
AddSemaphore(signalSemaphore)
             A1

void AddSemaphore(struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 0} instead.

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

Semaphores that are linked together in an allocation list (which @{"ObtainSemaphoreList()" LINK "ObtainSemaphoreList" 0} 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
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
signalSemaphore - an signal semaphore structure
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
Does not work in Exec < @{FG SHINE}V36@{FG TEXT}.  Instead use this code:
@{lindent 12}
#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" 33} *SysBase;
    ...
void LocalAddSemaphore(s)
struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *s;
{
    s->ss_Link.ln_Type=NT_SIGNALSEM;
    @{"InitSemaphore" LINK "InitSemaphore" 0}(s);
    @{"Forbid()" LINK "Forbid" 0};
    @{"Enqueue" LINK "Enqueue" 0}(&SysBase->SemaphoreList,s);
    @{"Permit()" LINK "Permit" 0};
}
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"RemSemaphore()" LINK "RemSemaphore" 0}, @{"FindSemaphore()" LINK "FindSemaphore" 0}, @{"InitSemaphore()" LINK "InitSemaphore" 0}
@ENDNODE

@NODE "AddTail" "exec.library/AddTail()"
@{jcenter}
@{u}@{b}AddTail()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AddTail - append node to tail of a list
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
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} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Add a node to the tail of a doubly linked list. Assembly programmers may prefer to use the ADDTAIL macro from @{"exec/lists.h" LINK "include:exec/lists.h/MAIN" 0}.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
This function does not arbitrate for access to the list. The calling task must be the owner of the involved list.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
list - a pointer to the target list header
node - a pointer to the node to insert at tail of the list
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddHead()" LINK "AddHead" 0}, @{"Enqueue()" LINK "Enqueue" 0}, @{"Insert()" LINK "Insert" 0}, @{"Remove()" LINK "Remove" 0}, @{"RemHead()" LINK "RemHead" 0}, @{"RemTail()" LINK "RemTail" 0}
@ENDNODE

@NODE "AddTask" "exec.library/AddTask()"
@{jcenter}
@{u}@{b}AddTask()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AddTask - add a task to the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
AddTask(task, initialPC, finalPC)
        A1    A2         A3

APTR AddTask(struct @{"Task" LINK "include:exec/tasks.h/MAIN" 23} *, APTR, APTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 0}). These will be automatically be deallocated at @{"RemTask()" LINK "RemTask" 0} time. If the code you have used to start the task has already added something to the MEMENTRY list, simply use @{"AddHead()" LINK "AddHead" 0} to add your new MemLists in. If no initialization has been done, a @{"NewList()" LINK "amiga_lib.guide/NewList" 0} will need to be performed.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 16}task  - pointer to the task control block (TCB). All unset fields must be zero.@{lindent 8}
initialPC - the initial entry point's address
@{lindent 18}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.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
For @{FG SHINE}V36@{FG TEXT}, AddTask returns either a NULL or the address of the new task. Old code need not check this.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
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.guide/CreateProc" 0} for information on Processes.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"RemTask()" LINK "RemTask" 0}, @{"FindTask()" LINK "FindTask" 0}, @{"amiga.lib/CreateTask()" LINK "amiga_lib.guide/CreateTask" 0}, @{"dos/CreateProc()" LINK "dos.guide/CreateProc" 0}, @{"amiga.lib/NewList()" LINK "amiga_lib.guide/NewList" 0}
@ENDNODE

@NODE "Alert" "exec.library/Alert()"
@{jcenter}
@{u}@{b}Alert()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Alert - alert the user of an error
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
Alert(alertNum)
      D7

void Alert(ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 @{FG SHINE}V39@{FG TEXT}:
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.
@{lindent 4}
@{fg shine}@{b}POST-MORTEM DIAGNOSIS@{ub}@{fg text}@{lindent 8}
There are several options for determining the cause of a crash. Descriptions of each alert number can be found in the @{"exec/alerts.h" LINK "include:exec/alerts.h/MAIN" 0} 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 on the remote terminal will invoke the ROM debugger.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
@{lindent 21}alertNum   - a number indicating the particular alert.  -1 is not a valid input.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
Much more needs to be said about this function and its implications.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/alerts.h" LINK "include:exec/alerts.h/MAIN" 0}
@ENDNODE

@NODE "AllocAbs" "exec.library/AllocAbs()"
@{jcenter}
@{u}@{b}AllocAbs()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AllocAbs - allocate at a given location
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
memoryBlock = AllocAbs(byteSize, location)
D0                     D0        A1

void *AllocAbs(ULONG, APTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.

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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 19}byteSize - the size of the desired block in bytes This number is rounded up to the next larger block size for the actual allocation.@{lindent 8}
location - the address where the memory MUST be.
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
@{lindent 22}memoryBlock - a pointer to the newly allocated memory block, or NULL if failed.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AllocMem()" LINK "AllocMem" 0}, @{"FreeMem()" LINK "FreeMem" 0}
@ENDNODE

@NODE "Allocate" "exec.library/Allocate()"
@{jcenter}
@{u}@{b}Allocate()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Allocate - allocate a block of memory
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
memoryBlock=Allocate(memHeader, byteSize)
D0                   A0         D0

void *Allocate(struct @{"MemHeader" LINK "include:exec/memory.h/MAIN" 27} *, ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 27} 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" 27} and associated free chunk list is done. You must be the owner before calling Allocate.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
memHeader - points to the local memory list header.
byteSize - the size of the desired block in bytes.
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
@{lindent 22}memoryBlock - a pointer to the just allocated free block. If there are no free regions large enough to satisfy the request, return zero.
@{lindent 4}
@{fg shine}@{b}EXAMPLE@{ub}@{fg text}@{lindent 8}
#include <@{"exec/types.h" LINK "include:exec/types.h/MAIN" 0}>
#include <@{"exec/memory.h" LINK "include:exec/memory.h/MAIN" 0}>
void *@{"AllocMem()" LINK "AllocMem" 0};
#define BLOCKSIZE 4096L /* Or whatever you want */

void main()
{
struct @{"MemHeader" LINK "include:exec/memory.h/MAIN" 27} *mh;
struct @{"MemChunk" LINK "include:exec/memory.h/MAIN" 19}  *mc;
APTR   block1;
APTR   block2;

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

    /* Get the actual block the above @{"MemHeader" LINK "include:exec/memory.h/MAIN" 27} will manage */
    mc = (struct @{"MemChunk" LINK "include:exec/memory.h/MAIN" 19} *)@{"AllocMem" LINK "AllocMem" 0}( BLOCKSIZE, 0L );
    if( !mc )
        {
        @{"FreeMem" LINK "FreeMem" 0}( mh, (long)sizeof(struct @{"MemHeader" LINK "include:exec/memory.h/MAIN" 27}) ); 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" LINK "amiga_lib.guide/printf" 0}("mh=$%lx mc=$%lx\n",mh,mc);
    @{"printf" LINK "amiga_lib.guide/printf" 0}("Block1=$%lx, Block2=$%lx\n",block1,block2);

    @{"FreeMem" LINK "FreeMem" 0}( mh, (long)sizeof(struct @{"MemHeader" LINK "include:exec/memory.h/MAIN" 27}) );
    @{"FreeMem" LINK "FreeMem" 0}( mc, BLOCKSIZE );
}
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
If the free list is corrupt, the system will panic with alert AN_MemCorrupt, $01000005.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"Deallocate()" LINK "Deallocate" 0}, @{"exec/memory.h" LINK "include:exec/memory.h/MAIN" 0}
@ENDNODE

@NODE "AllocEntry" "exec.library/AllocEntry()"
@{jcenter}
@{u}@{b}AllocEntry()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AllocEntry - allocate many regions of memory
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
memList = AllocEntry(memList)
D0                   A0

struct @{"MemList" LINK "include:exec/memory.h/MAIN" 55} *AllocEntry(struct @{"MemList" LINK "include:exec/memory.h/MAIN" 55} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 55} structure to keep track of it.

These @{"MemList" LINK "include:exec/memory.h/MAIN" 55} 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()" LINK "RemTask" 0}).
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
memList - A @{"MemList" LINK "include:exec/memory.h/MAIN" 55} structure filled in with @{"MemEntry" LINK "include:exec/memory.h/MAIN" 39} structures.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 19}memList - A different @{"MemList" LINK "include:exec/memory.h/MAIN" 55} 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.
@{lindent 4}
@{fg shine}@{b}EXAMPLES@{ub}@{fg text}@{lindent 8}
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:
@{lindent 12}
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
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/memory.h" LINK "include:exec/memory.h/MAIN" 0}
@ENDNODE

@NODE "AllocMem" "exec.library/AllocMem()"
@{jcenter}
@{u}@{b}AllocMem()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AllocMem - allocate memory given certain requirements
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
memoryBlock = AllocMem(byteSize, attributes)
D0                     D0        D1

void *AllocMem(ULONG, ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 19}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)
@{lindent 8}
attributes - requirements
@{lindent 16}
If no flags are set, the system will return the best available memory block. For expanded systems, the fast memory pool is searched first.

@{lindent 32}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-@{FG SHINE}V36@{FG TEXT} trackdisk.device buffers.
@{lindent 16}

@{lindent 32}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.
@{lindent 16}

@{lindent 32}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.
@{lindent 16}

@{lindent 32}MEMF_LOCAL:     This is memory that will not go away after the CPU @{"RESET" LINK "RESET" 0} instruction. Normally, autoconfig memory boards become unavailable after @{"RESET" LINK "RESET" 0} while motherboard memory may still be available. This memory type is now automatically set in @{FG SHINE}V36@{FG TEXT}. Pre-@{FG SHINE}V36@{FG TEXT} systems may not have this memory type and AllocMem() will then fail.
@{lindent 16}

@{lindent 32}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 @{FG SHINE}V36@{FG TEXT}. Pre-@{FG SHINE}V36@{FG TEXT} systems may not have this memory type and AllocMem() will then fail.
@{lindent 16}

@{lindent 32}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 @{FG SHINE}V39@{FG TEXT}. Pre-@{FG SHINE}V39@{FG TEXT} 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.

@{lindent 8}
@{b}    options@{ub}
@{lindent 16}
@{lindent 32}MEMF_CLEAR:     The memory will be initialized to all zeros.
@{lindent 16}

@{lindent 32}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 @{FG SHINE}V36@{FG TEXT}. Note that this option has a bug in pre-@{FG SHINE}V39@{FG TEXT} systems.
@{lindent 16}

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

@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
@{lindent 22}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.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}EXAMPLES@{ub}@{fg text}@{lindent 8}
@{lindent 34}AllocMem(64,0L)         - Allocate the best available memory@{lindent 8}
@{lindent 34}AllocMem(25,MEMF_CLEAR) - Allocate the best available memory, and clear it before returning.@{lindent 8}
@{lindent 34}AllocMem(128,MEMF_CHIP) - Allocate chip memory@{lindent 8}
@{lindent 45}AllocMem(128,MEMF_CHIP|MEMF_CLEAR) - Allocate cleared chip memory@{lindent 8}
@{lindent 57}AllocMem(821,MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR) - Allocate cleared, public, chip memory.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"FreeMem()" LINK "FreeMem" 0}
@ENDNODE

@NODE "AllocPooled" "exec.library/AllocPooled()"
@{jcenter}
@{u}@{b}AllocPooled()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AllocPooled - Allocate memory with the pool manager @{FG SHINE}(V39)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
memory=AllocPooled(poolHeader,memSize)
d0                 a0         d0

void *AllocPooled(void *,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Allocate memSize bytes of memory, and return a pointer. NULL is returned if the allocation fails.

Doing a @{"DeletePool()" LINK "DeletePool" 0} 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" 0} each allocation)
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
memSize - the number of bytes to allocate
poolHeader - a specific private pool header.
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
A pointer to the memory, or NULL.
The memory block returned is long word aligned.
@{lindent 4}
@{fg shine}@{b}NOTES@{ub}@{fg text}@{lindent 8}
The pool function 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" 0} 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" 0} and as such can only be protected by a semaphore.

To track sizes yourself, the following code can be used:
Assumes a6=@{"ExecBase" LINK "include:exec/execbase.h/MAIN" 33}

;
; 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, 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)
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"FreePooled()" LINK "FreePooled" 0}, @{"CreatePool()" LINK "CreatePool" 0}, @{"DeletePool()" LINK "DeletePool" 0}
@ENDNODE

@NODE "AllocSignal" "exec.library/AllocSignal()"
@{jcenter}
@{u}@{b}AllocSignal()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AllocSignal - allocate a signal bit
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
signalNum = AllocSignal(signalNum)
D0                      D0

BYTE AllocSignal(BYTE);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
Signals may not be allocated or freed from exception handling code.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 20}signalNum - the desired signal number {of 0..31} or -1 for no preference.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 20}signalNum - the signal bit number allocated {0..31}. If no signals are available, this function returns -1.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"FreeSignal()" LINK "FreeSignal" 0}
@ENDNODE

@NODE "AllocTrap" "exec.library/AllocTrap()"
@{jcenter}
@{u}@{b}AllocTrap()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AllocTrap - allocate a processor trap vector
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
trapNum = AllocTrap(trapNum)
D0                  D0

LONG AllocTrap(LONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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:
@{lindent 16}
@{lindent 24}0(SP) = Exception vector number. This will be in the range of 32 to 47 (corresponding to the Trap #1...Trap #15 instructions).@{lindent 16}
@{lindent 24}4(SP) = 68000/68010/68020/68030, etc. exception frame
@{lindent 8}
tc_TrapData is not used.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 18}trapNum - the desired trap number {of 0..15} or -1 for no preference.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 18}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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"FreeTrap()" LINK "FreeTrap" 0}
@ENDNODE

@NODE "AllocVec" "exec.library/AllocVec()"
@{jcenter}
@{u}@{b}AllocVec()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AllocVec - allocate memory and keep track of the size  @{FG SHINE}(V36)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
memoryBlock = AllocVec(byteSize, attributes)
D0                     D0        D1

void *AllocVec(ULONG, ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This function works identically to @{"AllocMem()" LINK "AllocMem" 0}, but tracks the size of the allocation.

See the @{"AllocMem()" LINK "AllocMem" 0} documentation for details.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"FreeVec()" LINK "FreeVec" 0}, @{"AllocMem()" LINK "AllocMem" 0}
@ENDNODE

@NODE "AttemptSemaphore" "exec.library/AttemptSemaphore()"
@{jcenter}
@{u}@{b}AttemptSemaphore()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AttemptSemaphore - try to obtain without blocking
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
success = AttemptSemaphore(signalSemaphore)
D0                         A0

LONG AttemptSemaphore(struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This call is similar to @{"ObtainSemaphore()" LINK "ObtainSemaphore" 0}, except that it will not block if the semaphore could not be locked.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
signalSemaphore - an initialized signal semaphore structure
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
success - TRUE if the semaphore was locked, false if some other task already possessed the semaphore.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
This call does NOT preserve registers.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"ObtainSemaphore()" LINK "ObtainSemaphore" 0} @{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}, @{"ReleaseSemaphore()" LINK "ReleaseSemaphore" 0}, @{"exec/semaphores.h" LINK "include:exec/semaphores.h/MAIN" 0}
@ENDNODE

@NODE "AttemptSemaphoreShared" "exec.library/AttemptSemaphoreShared()"
@{jcenter}
@{u}@{b}AttemptSemaphoreShared()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AttemptSemaphoreShared - try to obtain without blocking  @{FG SHINE}(V37)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
success = AttemptSemaphoreShared(signalSemaphore)
D0                               A0

LONG AttemptSemaphoreShared(struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This call is similar to @{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}, except that it will not block if the semaphore could not be locked.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
signalSemaphore - an initialized signal semaphore structure
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
success - TRUE if the semaphore was granted, false if some other task already possessed the semaphore in exclusive mode.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
This call does NOT preserve registers.

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

LONG myAttemptSempahoreShared(struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *ss)
{
LONG result;

        /* Try for a shared semaphore */
        if (!(result=AttemptSemaphoreShared(ss)))
        {
                /* Now try for the exclusive one... */
                result=AttempSemaphore(ss);
        }
        return(result);
}
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"ObtainSemaphore()" LINK "ObtainSemaphore" 0} @{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}, @{"ReleaseSemaphore()" LINK "ReleaseSemaphore" 0}, @{"exec/semaphores.h" LINK "include:exec/semaphores.h/MAIN" 0}
@ENDNODE

@NODE "AvailMem" "exec.library/AvailMem()"
@{jcenter}
@{u}@{b}AvailMem()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
AvailMem - memory available given certain requirements
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
size = AvailMem(attributes)
D0              D1

ULONG AvailMem(ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
Due to the effect of multitasking, the value returned may not actually be the amount of free memory available at that instant.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 23}requirements - a requirements mask as specified in @{"AllocMem()" LINK "AllocMem" 0}. Any of the @{"AllocMem()" LINK "AllocMem" 0} bits are valid, as is MEMF_LARGEST which returns the size of the largest block matching the requirements.
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
size - total free space remaining (or the largest free block).
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
For @{FG SHINE}V36@{FG TEXT} Exec, AvailMem(MEMF_LARGEST) does a consistency check on the memory list. Alert AN_MemoryInsane will be pulled if any mismatch is noted.
@{lindent 4}
@{fg shine}@{b}EXAMPLE@{ub}@{fg text}@{lindent 8}
AvailMem(MEMF_CHIP|MEMF_LARGEST);
/* return size of largest available chip memory chunk */
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/memory.h" LINK "include:exec/memory.h/MAIN" 0}
@ENDNODE

@NODE "CacheClearE" "exec.library/CacheClearE()"
@{jcenter}
@{u}@{b}CacheClearE()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CacheClearE - Cache clearing with extended control @{FG SHINE}(V37)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
CacheClearE(address,length,caches)
            a0      d0     d1

void CacheClearE(APTR,ULONG,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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:@{lindent 25}
Self modifying code
Building Jump tables
Run-time code patches
Relocating code for use at different addresses.
Loading code from disk
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 18}address - Address to start the operation. This may be rounded due to hardware granularity.@{lindent 8}
@{lindent 18}length  - Length of area to be cleared, or $FFFFFFFF to indicate all addresses should be cleared.@{lindent 8}
@{lindent 18}caches  - Bit flags to indicate what caches to affect. The current supported flags are:@{lindent 25}
CACRF_ClearI    ;Clear instruction cache
CACRF_ClearD    ;Clear data cache@{lindent @{lindent 19}
All other bits are reserved for future definition.
@{lindent 4}
@{fg shine}@{b}NOTES@{ub}@{fg text}@{lindent 8}
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 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.guide/LoadSeg" 0}, @{"MakeLibrary()" LINK "MakeLibrary" 0} and @{"SetFunction()" LINK "SetFunction" 0}.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/execbase.h" LINK "include:exec/execbase.h/MAIN" 0}, @{"CacheControl()" LINK "CacheControl" 0}, @{"CacheClearU()" LINK "CacheClearU" 0}
@ENDNODE

@NODE "CacheClearU" "exec.library/CacheClearU()"
@{jcenter}
@{u}@{b}CacheClearU()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CacheClearU - User callable simple cache clearing @{FG SHINE}(V37)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
CacheClearU()

void CacheClearU(void);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 0} autodoc for a more complete description.

Some examples of when the cache needs clearing:@{lindent 25}
Self modifying code
Building Jump tables
Run-time code patches
Relocating code for use at different addresses.
Loading code from disk
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/execbase.h" LINK "include:exec/execbase.h/MAIN" 0}, @{"CacheControl()" LINK "CacheControl" 0}, @{"CacheClearE()" LINK "CacheClearE" 0}
@ENDNODE

@NODE "CacheControl" "exec.library/CacheControl()"
@{jcenter}
@{u}@{b}CacheControl()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CacheControl - Instruction & data cache control
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
oldBits = CacheControl(cacheBits,cacheMask)
D0                     D0        D1

ULONG CacheControl(ULONG,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.h" LINK "include:exec/execbase.h/MAIN" 0} 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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
cacheBits - new values for the bits specified in cacheMask.

cacheMask - a mask with ones for all bits to be changed.
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
oldBits   - the complete prior values for all settings.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
As a side effect, this function clears all caches.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/execbase.h" LINK "include:exec/execbase.h/MAIN" 0}, @{"CacheClearU()" LINK "CacheClearU" 0}, @{"CacheClearE()" LINK "CacheClearE" 0}
@ENDNODE

@NODE "CachePostDMA" "exec.library/CachePostDMA()"
@{jcenter}
@{u}@{b}CachePostDMA()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CachePostDMA - Take actions after to hardware DMA  @{FG SHINE}(V37)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
CachePostDMA(vaddress,&length,flags)
             a0       a1      d0

CachePostDMA(APTR,LONG *,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 (MMU) activity.

As implemented@{lindent 17}
68000 - Do nothing
68010 - Do nothing
68020 - Do nothing
68030 - Flush the data cache
@{lindent 25}68040 - Flush matching areas of the data cache@{lindent 17}
@{lindent 25}????? - 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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
address - Same as initially passed to @{"CachePreDMA()" LINK "CachePreDMA" 0}
length  - Same as initially passed to @{"CachePreDMA()" LINK "CachePreDMA" 0}
flags   - Values:@{lindent 25}
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()
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/execbase.h" LINK "include:exec/execbase.h/MAIN" 0}, @{"CachePreDMA()" LINK "CachePreDMA" 0}, @{"CacheClearU()" LINK "CacheClearU" 0}, @{"CacheClearE()" LINK "CacheClearE" 0}
@ENDNODE

@NODE "CachePreDMA" "exec.library/CachePreDMA()"
@{jcenter}
@{u}@{b}CachePreDMA()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CachePreDMA - Take actions prior to hardware DMA  @{FG SHINE}(V37)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
paddress = CachePreDMA(vaddress,&length,flags)
d0                     a0       a1      d0

APTR CachePreDMA(APTR,LONG *,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 (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@{lindent 17}
68000 - Do nothing
68010 - Do nothing
68020 - Do nothing
68030 - Do nothing
@{lindent 25}68040 - 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.@{lindent 17}
@{lindent 25}????? - 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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
address - Base address to start the action.
length  - Pointer to a longword with a length.
flags   - Values:@{lindent 25}
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()
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 19}paddress - Physical address that corresponds to the input virtual address.@{lindent 8}
@{lindent 19}&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.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/execbase.h" LINK "include:exec/execbase.h/MAIN" 0}, @{"CachePostDMA()" LINK "CachePostDMA" 0}, @{"CacheClearU()" LINK "CacheClearU" 0}, @{"CacheClearE()" LINK "CacheClearE" 0}
@ENDNODE

@NODE "Cause" "exec.library/Cause()"
@{jcenter}
@{u}@{b}Cause()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Cause - cause a software interrupt
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
Cause(interrupt)
      A1

void Cause(struct @{"Interrupt" LINK "include:exec/interrupts.h/MAIN" 21} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
When setting up the Interrupt structure, set the node type to NT_INTERRUPT, or NT_UNKOWN.
@{lindent 4}
@{fg shine}@{b}IMPLEMENTATION@{ub}@{fg text}@{lindent 8}
@{lindent 11}1> Checks if the node type is NT_SOFTINT. If so does nothing since the softint is already pending.  No nest count is maintained.@{lindent 8}
@{lindent 11}2> Sets the node type to NT_SOFTINT.@{lindent 8}
@{lindent 11}3> Links into one of the 5 priority queues.@{lindent 8}
@{lindent 11}4> Pokes the hardware interrupt bit used for softints.@{lindent 8}

The node type returns to NT_INTERRUPT after removal from the list.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
interrupt - pointer to a properly initialized interrupt node
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
Unlike other Interrupts, SoftInts must preserve the value of A6.
@ENDNODE

@NODE "CheckIO" "exec.library/CheckIO()"
@{jcenter}
@{u}@{b}CheckIO()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CheckIO - get the status of an @{"IORequest" LINK "include:exec/io.h/MAIN" 17}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
result = CheckIO(iORequest)
D0               A1

struct @{"IORequest" LINK "include:exec/io.h/MAIN" 17} *CheckIO(struct @{"IORequest" LINK "include:exec/io.h/MAIN" 17} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This function determines the current state of an I/O request and
 returns FALSE 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" 17} from the reply port. This is best performed with @{"WaitIO()" LINK "WaitIO" 0}. If the request has already completed, @{"WaitIO()" LINK "WaitIO" 0} will return quickly. Use of the @{"Remove()" LINK "Remove" 0} function is dangerous, since other tasks may still be adding things to your message port; a @{"Disable()" LINK "Disable" 0} would be required.

This function should NOT be used to busy loop (looping until IO is complete). @{"WaitIO()" LINK "WaitIO" 0} is provided for that purpose.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
iORequest - pointer to an I/O request block
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 17}result - NULL if I/O is still in progress. Otherwise D0 points to the @{"IORequest" LINK "include:exec/io.h/MAIN" 17} block.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
CheckIO can hang if called on an @{"IORequest" LINK "include:exec/io.h/MAIN" 17} that has never been used. This occurs if LN_TYPE of the @{"IORequest" LINK "include:exec/io.h/MAIN" 17} is set to "NT_MESSAGE". Instead simply set LN_TYPE to 0.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"DoIO()" LINK "DoIO" 0}, @{"SendIO()" LINK "SendIO" 0}, @{"WaitIO()" LINK "WaitIO" 0}, @{"AbortIO()" LINK "AbortIO" 0}
@ENDNODE

@NODE "CloseDevice" "exec.library/CloseDevice()"
@{jcenter}
@{u}@{b}CloseDevice()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CloseDevice - conclude access to a device
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
CloseDevice(iORequest)
            A1

void CloseDevice(struct @{"IORequest" LINK "include:exec/io.h/MAIN" 17} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 "AbortIO" 0} function can kill any stragglers.

After a close, the I/O request structure is free to be reused. Starting with @{FG SHINE}V36@{FG TEXT} exec it is safe to CloseDevice() with an @{"IORequest" LINK "include:exec/io.h/MAIN" 17} that is either cleared to zeros, or failed to open.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
iORequest - pointer to an I/O request structure
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"OpenDevice()" LINK "OpenDevice" 0}
@ENDNODE

@NODE "CloseLibrary" "exec.library/CloseLibrary()"
@{jcenter}
@{u}@{b}CloseLibrary()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CloseLibrary - conclude access to a library
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
CloseLibrary(library)
             A1

void CloseLibrary(struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 @{FG SHINE}V36@{FG TEXT}, it is safe to pass a NULL instead of a library pointer.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
library - pointer to a library node
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
Library writers must pass a SegList pointer or NULL back from their open point. This value is used by the system, and not visible as a return code from CloseLibrary.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"OpenLibrary()" LINK "OpenLibrary" 0}
@ENDNODE

@NODE "ColdReboot" "exec.library/ColdReboot()"
@{jcenter}
@{u}@{b}ColdReboot()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
ColdReboot - reboot the Amiga @{FG SHINE}(V36)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
ColdReboot()

void ColdReboot(void);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Reboot the machine. All external memory and periperals will be @{"RESET" LINK "RESET" 0}, and the machine will start its power up diagnostics.

This function never returns.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
A chaotic pile of disoriented bits.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
An altogether totally integrated living system.
@ENDNODE

@NODE "CopyMem" "exec.library/CopyMem()"
@{jcenter}
@{u}@{b}CopyMem()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CopyMem - general purpose memory copy function
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
CopyMem( source, dest, size )
         A0      A1    D0

void CopyMem(APTR,APTR,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.

Arbitrary overlapping copies are not supported.

The internal implementation of this function will change from system to system, and may be implemented via hardware DMA.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 17}source - a pointer to the source data region@{lindent 8}
@{lindent 17}dest   - a pointer to the destination data region@{lindent 8}
@{lindent 17}size   - the size (in bytes) of the memory area. Zero copies zero bytes
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"CopyMemQuick()" LINK "CopyMemQuick" 0}
@ENDNODE

@NODE "CopyMemQuick" "exec.library/CopyMemQuick()"
@{jcenter}
@{u}@{b}CopyMemQuick()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CopyMemQuick - optimized memory copy function
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
CopyMemQuick( source, dest, size )
              A0      A1    D0

void CopyMemQuick(ULONG *,ULONG *,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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).

Arbitrary overlapping copies are not supported.

The internal implementation of this function will change from system to system, and may be implemented via hardware DMA.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 17}source - a pointer to the source data region, long aligned@{lindent 8}
@{lindent 17}dest   - a pointer to the destination data region, long aligned@{lindent 8}
@{lindent 17}size   - the size (in bytes) of the memory area. Zero copies zero bytes.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"CopyMem()" LINK "CopyMem" 0}
@ENDNODE

@NODE "CreateIORequest" "exec.library/CreateIORequest()"
@{jcenter}
@{u}@{b}CreateIORequest()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CreateIORequest() - create an @{"IORequest" LINK "include:exec/io.h/MAIN" 17} structure  @{FG SHINE}(V36)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
ioReq = CreateIORequest( ioReplyPort, size );
                         A0           D0

struct @{"IORequest" LINK "include:exec/io.h/MAIN" 17} *CreateIORequest(struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} *, ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" LINK "include:exec/ports.h/MAIN" 46}".
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 22}ioReplyPort - Pointer to a port for replies (an initialized message port, as created by @{"CreateMsgPort()" LINK "CreateMsgPort" 0} ). If NULL, this function fails.@{lindent 8}
size - the size of the IO request to be created.
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
ioReq - A pointer to the new @{"IORequest" LINK "include:exec/io.h/MAIN" 17} block, or NULL.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"DeleteIORequest()" LINK "DeleteIORequest" 0}, @{"CreateMsgPort()" LINK "CreateMsgPort" 0}, @{"amiga.lib/CreateExtIO()" LINK "amiga_lib.guide/CreateExtIO" 0}
@ENDNODE

@NODE "CreateMsgPort" "exec.library/CreateMsgPort()"
@{jcenter}
@{u}@{b}CreateMsgPort()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CreateMsgPort - Allocate and initialize a new message port  @{FG SHINE}(V36)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
CreateMsgPort()

struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} * CreateMsgPort(void);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Allocates and initializes a new message port. The message list of the new port will be prepared for use (via @{"NewList" LINK "amiga_lib.guide/NewList" 0}). 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" 0} to delete ports created with CreateMsgPort()!
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
@{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} - A new @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} structure ready for use, or NULL if out of memory or signals. If you wish to add this port to the public port list, fill in the ln_Name and ln_Pri fields, then call @{"AddPort()" LINK "AddPort" 0}.  Don't forget @{"RemPort()" LINK "RemPort" 0}!
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"DeleteMsgPort()" LINK "DeleteMsgPort" 0}, @{"AddPort()" LINK "AddPort" 0}, @{"exec/ports.h" LINK "include:exec/ports.h/MAIN" 0}, @{"amiga.lib/CreatePort()" LINK "amiga_lib.guide/CreatePort" 0}
@ENDNODE

@NODE "CreatePool" "exec.library/CreatePool()"
@{jcenter}
@{u}@{b}CreatePool()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
CreatePool - Generate a private memory pool header @{FG SHINE}(V39)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
newPool=CreatePool(memFlags,puddleSize,threshSize)
a0                 d0       d1         d2

void *CreatePool(ULONG,ULONG,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 19}memFlags - a memory flags specifier, as taken by @{"AllocMem()" LINK "AllocMem" 0}.@{lindent 8}
puddleSize - the size of Puddles...
@{lindent 21}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)
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
The address of a new pool header, or NULL for error.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"DeletePool()" LINK "DeletePool" 0}, @{"AllocPooled()" LINK "AllocPooled" 0}, @{"FreePooled()" LINK "FreePooled" 0}, @{"exec/memory.h" LINK "include:exec/memory.h/MAIN" 0}
@ENDNODE

@NODE "Deallocate" "exec.library/Deallocate()"
@{jcenter}
@{u}@{b}Deallocate()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Deallocate - deallocate a block of memory
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
Deallocate(memHeader, memoryBlock, byteSize)
           A0         A1           D0

void Deallocate(struct @{"MemHeader" LINK "include:exec/memory.h/MAIN" 27} *,APTR,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 27}, however the extent pointers in the @{"MemHeader" LINK "include:exec/memory.h/MAIN" 27} 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" 0}. 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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 20}memHeader - points to the memory header this block is part of.@{lindent 8}
@{lindent 22}memoryBlock - address of memory block to free.@{lindent 8}
@{lindent 19}byteSize - the size of the block in bytes. If NULL, nothing happens.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"Allocate()" LINK "Allocate" 0}, @{"exec/memory.h" LINK "include:exec/memory.h/MAIN" 0}
@ENDNODE

@NODE "Debug" "exec.library/Debug()"
@{jcenter}
@{u}@{b}Debug()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Debug - run the system debugger
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
Debug(flags)
      D0

void Debug(ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This function calls the system debugger. By default this debugger is "SAD" in >= @{FG SHINE}V39@{FG TEXT} and "ROM-WACK" in < @{FG SHINE}V39@{FG TEXT}. Other debuggers are encouraged to take over this entry point (via @{"SetFunction()" LINK "SetFunction" 0}) so that when an application calls Debug(), the alternative debugger will get control. Currently a zero is passed to allow future expansion.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
The Debug() call may be made when the system is in a questionable state; if you have a @{"SetFunction()" LINK "SetFunction" 0} patch, make few assumptions, be prepared for Supervisor mode, and be aware of differences in the Motorola stack frames on the 68000,'10,'20,'30,'40 (etc.)
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
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. As of @{FG SHINE}V39@{FG TEXT} (and the instroduction of SAD) this is no longer the case. However, calling this function in Supervisor state is a bit "tricky" at best...

Note that due to a bug, pre-@{FG SHINE}V40@{FG TEXT} SAD had the command codes wrong. See the SAD autodoc for more details.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"SetFunction()" LINK "SetFunction" 0}
your favorite debugger's manual...
the SAD autodocs...
the ROM-WACK chapter of the ROM Kernel Manual... (pre-@{FG SHINE}V39@{FG TEXT})
@ENDNODE

@NODE "DeleteIORequest" "exec.library/DeleteIORequest()"
@{jcenter}
@{u}@{b}DeleteIORequest()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
DeleteIORequest() - Free a request made by @{"CreateIORequest()" LINK "CreateIORequest" 0}  @{FG SHINE}(V36)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
DeleteIORequest( ioReq );
                 a0

void DeleteIORequest(struct @{"IORequest" LINK "include:exec/io.h/MAIN" 17} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Frees up an IO request as allocated by @{"CreateIORequest()" LINK "CreateIORequest" 0}.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 16}ioReq - A pointer to the @{"IORequest" LINK "include:exec/io.h/MAIN" 17} block to be freed, or NULL.
This function uses the mn_Length field to determine how much memory to free.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"CreateIORequest()" LINK "CreateIORequest" 0}, @{"amiga.lib/DeleteExtIO()" LINK "amiga_lib.guide/DeleteExtIO" 0}
@ENDNODE

@NODE "DeleteMsgPort" "exec.library/DeleteMsgPort()"
@{jcenter}
@{u}@{b}DeleteMsgPort()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
DeleteMsgPort - Free a message port created by @{"CreateMsgPort()" LINK "CreateMsgPort" 0}  @{FG SHINE}(V36)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
DeleteMsgPort(msgPort)
              a0

void DeleteMsgPort(struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Frees a message port created by @{"CreateMsgPort()" LINK "CreateMsgPort" 0}. All messages that may have been attached to this port must have already been replied to.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
msgPort - A message port. NULL for no action.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"CreateMsgPort()" LINK "CreateMsgPort" 0}, @{"amiga.lib/DeletePort()" LINK "amiga_lib.guide/DeletePort" 0}
@ENDNODE

@NODE "DeletePool" "exec.library/DeletePool()"
@{jcenter}
@{u}@{b}DeletePool()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
DeletePool -  Drain an entire memory pool @{FG SHINE}(V39)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
DeletePool(poolHeader)
           a0

void DeletePool(void *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Frees all memory in all pudles of the specified pool header, then deletes the pool header. Individual free calls are not needed.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
poolHeader - as returned by @{"CreatePool()" LINK "CreatePool" 0}.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"CreatePool()" LINK "CreatePool" 0}, @{"AllocPooled()" LINK "AllocPooled" 0}, @{"FreePooled()" LINK "FreePooled" 0}
@ENDNODE

@NODE "Disable" "exec.library/Disable()"
@{jcenter}
@{u}@{b}Disable()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Disable - disable interrupt processing.
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
Disable();

void Disable(void);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Prevents interrupts from being handled by the system, until a matching @{"Enable()" LINK "Enable" 0} is executed. Disable() implies @{"Forbid()" LINK "Forbid" 0}.

DO NOT USE THIS CALL WITHOUT GOOD JUSTIFICATION. THIS CALL IS VERY DANGEROUS!
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
All interrupt processing is deferred until the task executing makes
 a call to @{"Enable()" LINK "Enable" 0} 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" 0} 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).

@{lindent 14}Note: In the event of a task entering a @{"Wait()" LINK "Wait" 0} after disabling interrupts, the system "breaks" the disabled state and runs normally until the task which called Disable() is rescheduled.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
This call is guaranteed to preserve all registers.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"Forbid()" LINK "Forbid" 0}, @{"Permit()" LINK "Permit" 0}, @{"Enable()" LINK "Enable" 0}
@ENDNODE

@NODE "DoIO" "exec.library/DoIO()"
@{jcenter}
@{u}@{b}DoIO()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
DoIO - perform an I/O command and wait for completion
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
error = DoIO(iORequest)
D0           A1

BYTE DoIO(struct @{"IORequest" LINK "include:exec/io.h/MAIN" 17} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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..
@{lindent 4}
@{fg shine}@{b}IMPLEMENTATION@{ub}@{fg text}@{lindent 8}
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 LN_TYPE field is used internally to flag completion. Active requests have type NT_MESSAGE. Requests that have been replied have type NT_REPLYMSG. It is illegal to start IO using a still active @{"IORequest" LINK "include:exec/io.h/MAIN" 17}, or a request with type NT_REPLYMSG.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
iORequest - pointer to an @{"IORequest" LINK "include:exec/io.h/MAIN" 17} initialized by @{"OpenDevice()" LINK "OpenDevice" 0}
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 16}error - a sign-extended copy of the io_Error field of the @{"IORequest" LINK "include:exec/io.h/MAIN" 17}. Most device commands require that the error return be checked.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"SendIO()" LINK "SendIO" 0}, @{"CheckIO()" LINK "CheckIO" 0}, @{"WaitIO()" LINK "WaitIO" 0}, @{"AbortIO()" LINK "AbortIO" 0}, @{"amiga.lib/BeginIO()" LINK "amiga_lib.guide/BeginIO" 0}
@ENDNODE

@NODE "Enable" "exec.library/Enable()"
@{jcenter}
@{u}@{b}Enable()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Enable - permit system interrupts to resume.
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
Enable();

void Enable(void);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Allow system interrupts to again occur normally, after a matching @{"Disable()" LINK "Disable" 0} has been executed.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
Interrupt processing is restored to normal operation. The programmer must execute exactly one call to Enable() for every call to @{"Disable()" LINK "Disable" 0}.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
This call is guaranteed to preserve all registers.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"Forbid()" LINK "Forbid" 0}, @{"Permit()" LINK "Permit" 0}, @{"Disable()" LINK "Disable" 0}
@ENDNODE

@NODE "Enqueue" "exec.library/Enqueue()"
@{jcenter}
@{u}@{b}Enqueue()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Enqueue - insert or append node to a system queue
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
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} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Insert or append a node into a system queue. The insert 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
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
This function does not arbitrate for access to the list. The calling task must be the owner of the involved list.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 15}list - a pointer to the system queue header@{lindent 8}
@{lindent 15}node - the node to enqueue. This must be a full featured node with type, priority and name fields.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddHead()" LINK "AddHead" 0}, @{"AddTail()" LINK "AddTail" 0}, @{"Insert()" LINK "Insert" 0}, @{"Remove()" LINK "Remove" 0}, @{"RemHead()" LINK "RemHead" 0}, @{"RemTail()" LINK "RemTail" 0}
@ENDNODE

@NODE "FindName" "exec.library/FindName()"
@{jcenter}
@{u}@{b}FindName()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FindName - find a system list node with a given name
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
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);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 16}start - a list header or a list node to start the search (if node, this one is skipped)@{lindent 8}
@{lindent 16}name  - a pointer to a name string terminated with NULL
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 15}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()"
@{jcenter}
@{u}@{b}FindPort()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FindPort - find a given system message port
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
port = FindPort(name)
D0              A1

struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} *FindPort(STRPTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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()" LINK "Forbid" 0}/@{"Permit()" LINK "Permit" 0} pair!
@{lindent 4}
@{fg shine}@{b}EXAMPLE@{ub}@{fg text}@{lindent 8}
#include <@{"exec/types.h" LINK "include:exec/types.h/MAIN" 0}>
struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} *FindPort();

ULONG SafePutToPort(message, portname)
struct @{"Message" LINK "include:exec/ports.h/MAIN" 46} *message;
STRPTR          portname;
{
struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} *port;

    @{"Forbid()" LINK "Forbid" 0};
        port = FindPort(portname);
        if (port)
            @{"PutMsg" LINK "PutMsg" 0}(port,message);
    @{"Permit()" LINK "Permit" 0};
    return((ULONG)port); /* If zero, the port has gone away */
}
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
name - name of the port to find
@{lindent 4}
@{fg shine}@{b}RETURN@{ub}@{fg text}@{lindent 8}
@{lindent 15}port - a pointer to the message port, or zero if not found.
@ENDNODE

@NODE "FindResident" "exec.library/FindResident()"
@{jcenter}
@{u}@{b}FindResident()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FindResident - find a resident module by name
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
resident = FindResident(name)
D0                      A1

struct @{"Resident" LINK "include:exec/resident.h/MAIN" 17} *FindResident(STRPTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 modules are used by the system to pull all its parts together at startup. Resident tags are also found in disk based devices and libraries.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
name - pointer to name string
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
@{lindent 19}resident - pointer to the resident tag structure or zero if none found.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/resident.h" LINK "include:exec/resident.h/MAIN" 0}, @{"InitResident()" LINK "InitResident" 0}
@ENDNODE

@NODE "FindSemaphore" "exec.library/FindSemaphore()"
@{jcenter}
@{u}@{b}FindSemaphore()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FindSemaphore - find a given system signal semaphore
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
signalSemaphore = FindSemaphore(name)
D0                              A1

struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *FindSemaphore(STRPTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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()" LINK "Forbid" 0}/@{"Permit()" LINK "Permit" 0} pair.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
name - name of the semaphore to find
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
@{lindent 20}semaphore - a pointer to the signal semaphore, or zero if not found.
@ENDNODE

@NODE "FindTask" "exec.library/FindTask()"
@{jcenter}
@{u}@{b}FindTask()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FindTask - find a task with the given name or find oneself
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
task = FindTask(name)
D0              A1

struct @{"Task" LINK "include:exec/tasks.h/MAIN" 23} *FindTask(STRPTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 name pointer is given a pointer to the current task will be returned.

Finding oneself with a 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()" LINK "Forbid" 0}/@{"Permit()" LINK "Permit" 0} pair may be needed to ensure the pointer returned by FindTask() is still valid when used.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
name - pointer to a name string
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
task - pointer to the task (or Process)
@ENDNODE

@NODE "Forbid" "exec.library/Forbid()"
@{jcenter}
@{u}@{b}Forbid()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Forbid - forbid task rescheduling.
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
Forbid()

void Forbid(void);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Prevents other tasks from being scheduled to run by the dispatcher, until a matching @{"Permit()" LINK "Permit" 0} is executed, or this task is scheduled to @{"Wait()" LINK "Wait" 0}. Interrupts are NOT disabled.

DO NOT USE THIS CALL WITHOUT GOOD JUSTIFICATION. THIS CALL IS DANGEROUS!
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
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" 0} for every call to Forbid().
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
In the event of a task entering a @{"Wait()" LINK "Wait" 0} 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()).
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
This call is guaranteed to preserve all registers.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"Permit()" LINK "Permit" 0}, @{"Disable()" LINK "Disable" 0}, @{"ObtainSemaphore()" LINK "ObtainSemaphore" 0}, @{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}
@ENDNODE

@NODE "FreeEntry" "exec.library/FreeEntry()"
@{jcenter}
@{u}@{b}FreeEntry()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FreeEntry - free many regions of memory
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
FreeEntry(memList)
          A0
void FreeEntry(struct @{"MemList" LINK "include:exec/memory.h/MAIN" 55} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This function takes a memList structure (as returned by @{"AllocEntry()" LINK "AllocEntry" 0}) and frees all the entries.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 19}memList - pointer to structure filled in with @{"MemEntry" LINK "include:exec/memory.h/MAIN" 39} structures
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AllocEntry()" LINK "AllocEntry" 0}
@ENDNODE

@NODE "FreeMem" "exec.library/FreeMem()"
@{jcenter}
@{u}@{b}FreeMem()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FreeMem - deallocate with knowledge
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
FreeMem(memoryBlock, byteSize)
        A1           D0

void FreeMem(void *,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
If a block of memory is freed twice, the system will Guru. The 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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 22}memoryBlock - pointer to the memory block to free@{lindent 8}
@{lindent 19}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)
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AllocMem()" LINK "AllocMem" 0}
@ENDNODE

@NODE "FreePooled" "exec.library/FreePooled()"
@{jcenter}
@{u}@{b}FreePooled()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FreePooled - Free pooled memory  @{FG SHINE}(V39)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
FreePooled(poolHeader,memory,memSize)
           a0         a1     d0

void FreePooled(void *,void *,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Deallocates memory allocated by @{"AllocPooled()" LINK "AllocPooled" 0}. The size of the allocation *MUST* match the size given to @{"AllocPooled()" LINK "AllocPooled" 0}. 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" 0} may be freed with this function!

Doing a @{"DeletePool()" LINK "DeletePool" 0} on the pool will free all of the puddles and thus all of the allocations done with @{"AllocPooled()" LINK "AllocPooled" 0} in that pool. (No need to FreePooled() each allocation)
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
memory - pointer to memory allocated by @{"AllocPooled()" LINK "AllocPooled" 0}.
poolHeader - a specific private pool header.
@{lindent 4}
@{fg shine}@{b}NOTES@{ub}@{fg text}@{lindent 8}
The pool function 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" 0} 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" 0} and as such can only be protected by a semaphore.

To track sizes yourself, the following code can be used:
Assumes a6=@{"ExecBase" LINK "include:exec/execbase.h/MAIN" 33}

;
; Function to do AllocVecPooled(Pool,memSize)
;
@{lindent 24}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, failed!
move.l  d0,a0           ; Get pointer...
move.l  d1,(a0)+        ; Store size
move.l  a0,d0           ; Get result@{lindent 8}
avp_fail:       rts                     ; return

;
; Function to do FreeVecPooled(pool,memory)
;
@{lindent 24}FreeVecPooled:  move.l  -(a1),d0        ; Get size / ajust pointer
jmp     _LVOFreePooled(a6)
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AllocPooled()" LINK "AllocPooled" 0}, @{"CreatePool()" LINK "CreatePool" 0}, @{"DeletePool()" LINK "DeletePool" 0}
@ENDNODE

@NODE "FreeSignal" "exec.library/FreeSignal()"
@{jcenter}
@{u}@{b}FreeSignal()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FreeSignal - free a signal bit
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
FreeSignal(signalNum)
           D0

void FreeSignal(BYTE);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
Signals may not be allocated or freed from exception handling code.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
Starting with @{FG SHINE}V37@{FG TEXT}, an attempt to free signal -1 is harmless.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
signalNum - the signal number to free {0..31}.
@ENDNODE

@NODE "FreeTrap" "exec.library/FreeTrap()"
@{jcenter}
@{u}@{b}FreeTrap()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FreeTrap - free a processor trap
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
FreeTrap(trapNum)
         D0

void FreeTrap(ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
Traps may not be allocated or freed from exception handling code.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
trapNum - the trap number to free {of 0..15}
@ENDNODE

@NODE "FreeVec" "exec.library/FreeVec()"
@{jcenter}
@{u}@{b}FreeVec()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
FreeVec - return @{"AllocVec()" LINK "AllocVec" 0} memory to the system  @{FG SHINE}(V36)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
FreeVec(memoryBlock)
        A1

void FreeVec(void *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Free an allocation made by the @{"AllocVec()" LINK "AllocVec" 0} call. The memory will be returned to the system pool from which it came.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
If a block of memory is freed twice, the system will Guru. The 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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
memoryBlock - pointer to the memory block to free, or NULL.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AllocVec()" LINK "AllocVec" 0}
@ENDNODE

@NODE "GetCC" "exec.library/GetCC()"
@{jcenter}
@{u}@{b}GetCC()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
GetCC - get condition codes in a 68010 compatible way.
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
conditions = GetCC()
D0

UWORD GetCC(void);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
conditions - the 680XX condition codes
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
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()"
@{jcenter}
@{u}@{b}GetMsg()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
GetMsg - get next message from a message port
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
message = GetMsg(port)
D0               A0

struct @{"Message" LINK "include:exec/ports.h/MAIN" 46} *GetMsg(struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 0} on the signal specified for the port or use the @{"WaitPort()" LINK "WaitPort" 0} 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" 0} 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" 0} or @{"WaitPort()" LINK "WaitPort" 0}.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
port - a pointer to the receiver message port
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
@{lindent 18}message - a pointer to the first message available. If there are no messages, return zero. Callers must be prepared for zero at any time.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"PutMsg()" LINK "PutMsg" 0}, @{"ReplyMsg()" LINK "ReplyMsg" 0}, @{"WaitPort()" LINK "WaitPort" 0}, @{"Wait()" LINK "Wait" 0}, @{"exec/ports.h" LINK "include:exec/ports.h/MAIN" 0}
@ENDNODE

@NODE "InitCode" "exec.library/InitCode()"
@{jcenter}
@{u}@{b}InitCode()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
InitCode - initialize resident code modules (internal function)
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
InitCode(startClass, version)
         D0          D1

void InitCode(ULONG,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
(This function may be ignored by application programmers)

Call @{"InitResident()" LINK "InitResident" 0} 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 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).
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
startClass - the class of code to be initialized:@{lindent 16}
BITDEF RT,COLDSTART,0
BITDEF RT,SINGLETASK,1  ;@{"ExecBase" LINK "include:exec/execbase.h/MAIN" 33}->ThisTask==0 @{FG SHINE}(V36 only)@{FG TEXT}
BITDEF RT,AFTERDOS,2    ;@{FG SHINE}(V36 only)@{FG TEXT}@{lindent 8}
version - a major version number
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
ResidentTag (RT) structure definition (resident.h)
@ENDNODE

@NODE "InitResident" "exec.library/InitResident()"
@{jcenter}
@{u}@{b}InitResident()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
InitResident - initialize resident module
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
object = InitResident(resident, segList)
D0                     A1        D1

APTR InitResident(struct @{"Resident" LINK "include:exec/resident.h/MAIN" 17} *,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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:@{lindent 16}
D0 = 0
A0 = segList
A6 = @{"ExecBase" LINK "include:exec/execbase.h/MAIN" 33}
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
resident - Pointer to a ROMTag
@{lindent 19}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 for ROM modules.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 18}object  - Return value from the init code, usually the library or device base. NULL for failure.
@{lindent 4}
@{fg shine}@{b}AUTOINIT FEATURE@{ub}@{fg text}@{lindent 8}
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 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()" LINK "MakeLibrary" 0};
@{lindent 13}
@{lindent 15}- The size of your library/device base structure including initial Library or Device structure.
@{lindent 13}
@{lindent 15}- A pointer to a longword table of standard, then library specific function offsets, terminated with -1L. (short format offsets are also acceptable)
@{lindent 13}
@{lindent 15}- Pointer to data table in exec/InitStruct format for initialization of Library or Device structure.
@{lindent 13}
@{lindent 15}- Pointer to library initialization function, or NULL.@{lindent 16}
Calling sequence:@{lindent 25}
D0 = library base
A0 = segList
A6 = @{"ExecBase" LINK "include:exec/execbase.h/MAIN" 33}@{lindent 16}
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 returned in D0.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/resident.h" LINK "include:exec/resident.h/MAIN" 0}, @{"FindResident()" LINK "FindResident" 0}
@ENDNODE

@NODE "InitSemaphore" "exec.library/InitSemaphore()"
@{jcenter}
@{u}@{b}InitSemaphore()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
InitSemaphore - initialize a signal semaphore
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
InitSemaphore(signalSemaphore)
              A0

void InitSemaphore(struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 0}, 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" 0}, 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()" LINK "Forbid" 0}/@{"Permit()" LINK "Permit" 0} type arbitration. With @{"Forbid()" LINK "Forbid" 0}/@{"Permit()" LINK "Permit" 0} *all* other tasks are prevented from running. With semaphores, only those tasks that need access to whatever the semaphore protects are subject to waiting.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
@{lindent 27}signalSemaphore - a signal semaphore structure (with all fields set to zero before the call)
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"ObtainSemaphore()" LINK "ObtainSemaphore" 0}, @{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}, @{"AttemptSemaphore()" LINK "AttemptSemaphore" 0}, @{"ReleaseSemaphore()" LINK "ReleaseSemaphore" 0}, @{"Procure()" LINK "Procure" 0}, @{"Vacate()" LINK "Vacate" 0}, @{"exec/semaphores.h" LINK "include:exec/semaphores.h/MAIN" 0}
@ENDNODE

@NODE "InitStruct" "exec.library/InitStruct()"
@{jcenter}
@{u}@{b}InitStruct()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
InitStruct - initialize memory from a table
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
InitStruct(initTable, memory, size);
           A1         A2      D0

void InitStruct(struct InitStruct *, APTR, ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.h" LINK "include:exec/initializers.h/MAIN" 0}".

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@{lindent 12}
dd  the destination type (and size):@{lindent 16}
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@{lindent 12}
ss  the size and location of the source:@{lindent 16}
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)@{lindent 10}
nnnn  the count or repeat:@{lindent 12}
count  the (number+1) of source items to copy
repeat  the source is copied (number+1) times.
@{lindent 8}
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 not supported for 68020 compatibility - use long.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 20}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".@{lindent 8}
@{lindent 20}memory    - the beginning of the memory to initialize. Must be on an even boundary if size is specified.@{lindent 8}
@{lindent 20}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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"exec/initializers.h" LINK "include:exec/initializers.h/MAIN" 0}
@ENDNODE

@NODE "Insert" "exec.library/Insert()"
@{jcenter}
@{u}@{b}Insert()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Insert - insert a node into a list
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
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} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 "AddHead" 0} function is slightly faster for that special case.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
This function does not arbitrate for access to the list. The calling task must be the owner of the involved list.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
list - a pointer to the target list header
node - the node to insert
listNode - the node after which to insert
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddHead()" LINK "AddHead" 0}, @{"AddTail()" LINK "AddTail" 0}, @{"Enqueue()" LINK "Enqueue" 0}, @{"RemHead()" LINK "RemHead" 0}, @{"Remove()" LINK "Remove" 0}, @{"RemTail()" LINK "RemTail" 0}
@ENDNODE

@NODE "MakeFunctions" "exec.library/MakeFunctions()"
@{jcenter}
@{u}@{b}MakeFunctions()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
MakeFunctions - construct a function jump table
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
tableSize = MakeFunctions(target, functionArray, funcDispBase)
D0                        A0      A1             A2

ULONG MakeFunctions(APTR,APTR,APTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
A low level function used by @{"MakeLibrary()" LINK "MakeLibrary" 0} 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.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
@{lindent 22}destination - the target address for the high memory end of the function jump table. Typically this will be the library base pointer.
@{lindent 8}
@{lindent 24}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.
@{lindent 8}
@{lindent 23}funcDispBase - pointer to the base about which all function displacements are relative. If zero, then the function array contains absolute pointers.
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
tableSize - size of the new table in bytes (for LIB_NEGSIZE).
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"MakeLibrary()" LINK "MakeLibrary" 0}
@ENDNODE

@NODE "MakeLibrary" "exec.library/MakeLibrary()"
@{jcenter}
@{u}@{b}MakeLibrary()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
MakeLibrary - construct a library
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
library = MakeLibrary(vectors, structure, init, dSize, segList)
D0                    A0       A1         A2    D0     D1

struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33} *MakeLibrary(APTR,struct @{"InitStruct" LINK "InitStruct" 0} *,APTR,ULONG,BPTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
 Starting with @{FG SHINE}V36@{FG TEXT}, the library base is longword adjusted. The lib_PosSize and lib_NegSize fields of the library structure are adjusted to match.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 18}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).
@{lindent 8}
@{lindent 20}structure - points to an "@{"InitStruct()" LINK "InitStruct" 0}" data region. If NULL, then it will not be used.
@{lindent 8}
@{lindent 15}init - If non-NULL, an entry point that will be called before adding the library to the system. Registers are as follows:@{lindent 24}
d0 = libAddr    ;Your Library Address
a0 = segList    ;Your AmigaDOS segment list
a6 = @{"ExecBase" LINK "include:exec/execbase.h/MAIN" 33}   ;Address of exec.library@{lindent 15}
The result of the init function must be the library address, or NULL for failure. If NULL, the init point must manually deallocate the library base memory (based on the sizes stored in lib_PosSize and lib_NegSize).
@{lindent 8}
@{lindent 16}dSize - the size of the library data area, including the standard library node data. This must be at leas sizeof(struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33}).
@{lindent 8}
@{lindent 18}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.
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
@{lindent 18}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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"InitStruct()" LINK "InitStruct" 0}, @{"InitResident()" LINK "InitResident" 0}, @{"exec/initializers.h" LINK "include:exec/initializers.h/MAIN" 0}
@ENDNODE

@NODE "ObtainQuickVector" "exec.library/ObtainQuickVector()"
@{jcenter}
@{u}@{b}ObtainQuickVector()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
ObtainQuickVector - obtain an install a Quick Interrupt vector  @{FG SHINE}(V39)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
vector=ObtainQuickVector(interruptCode)
d0                       a0

ULONG ObtainQuickVector(APTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 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 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.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
This function was not implemented fully until @{FG SHINE}V39@{FG TEXT}. Due to a mis-cue it is not safe to call in @{FG SHINE}V37@{FG TEXT} EXEC. (Sorry)
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
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.
@ENDNODE

@NODE "ObtainSemaphore" "exec.library/ObtainSemaphore()"
@{jcenter}
@{u}@{b}ObtainSemaphore()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
ObtainSemaphore - gain exclusive access to a semaphore
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
ObtainSemaphore(signalSemaphore)
                A0

void ObtainSemaphore(struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 0} 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 Semaphores are different than @{"Procure()" LINK "Procure" 0}/@{"Vacate()" LINK "Vacate" 0} 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.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
signalSemaphore - an initialized signal semaphore structure
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
This function preserves all registers (see BUGS).
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
Until @{FG SHINE}V37@{FG TEXT}, this function could destroy A0.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}, @{"InitSemaphore()" LINK "InitSemaphore" 0}, @{"ReleaseSemaphore()" LINK "ReleaseSemaphore" 0}, @{"AttemptSemaphore()" LINK "AttemptSemaphore" 0}, @{"ObtainSemaphoreList()" LINK "ObtainSemaphoreList" 0}, @{"Procure()" LINK "Procure" 0}, @{"Vacate()" LINK "Vacate" 0}
@ENDNODE

@NODE "ObtainSemaphoreList" "exec.library/ObtainSemaphoreList()"
@{jcenter}
@{u}@{b}ObtainSemaphoreList()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
ObtainSemaphoreList - get a list of semaphores.
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
ObtainSemaphoreList(list)
                    A0

void ObtainSemaphoreList(struct @{"List" LINK "include:exec/lists.h/MAIN" 19} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 0} 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" 0} 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)
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
list - a list of signal semaphores
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}, @{"InitSemaphore()" LINK "InitSemaphore" 0}, @{"ReleaseSemaphore()" LINK "ReleaseSemaphore" 0}, @{"AttemptSemaphore()" LINK "AttemptSemaphore" 0}, @{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}, @{"Procure()" LINK "Procure" 0}, @{"Vacate()" LINK "Vacate" 0}
@ENDNODE

@NODE "ObtainSemaphoreShared" "exec.library/ObtainSemaphoreShared()"
@{jcenter}
@{u}@{b}ObtainSemaphoreShared()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
ObtainSemaphoreShared - gain shared access to a semaphore @{FG SHINE}(V36)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
ObtainSemaphoreShared(signalSemaphore)
                      a0

void ObtainSemaphoreShared(struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
A lock on a signal semaphore may either be exclusive, or shared. Exclusive locks are granted by the @{"ObtainSemaphore()" LINK "ObtainSemaphore" 0} and @{"AttemptSemaphore()" LINK "AttemptSemaphore" 0} 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.
@{lindent 4}
@{fg shine}@{b}EXAMPLE@{ub}@{fg text}@{lindent 16}
ObtainSemaphoreShared(ss);
/* read data */
ReleaseSemaohore(ss);

@{"ObtainSemaphore" LINK "ObtainSemaphore" 0}(ss);
/* modify data */
ReleaseSemaohore(ss);
@{lindent 4}
@{fg shine}@{b}NOTES@{ub}@{fg text}@{lindent 8}
While this function was added for @{FG SHINE}V36@{FG TEXT}, 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 @{FG SHINE}V39@{FG TEXT}, if the caller already has an exclusive lock on the semaphore it will return with another nesting of the lock. Pre-@{FG SHINE}V39@{FG TEXT} this would cause a deadlock. For pre-@{FG SHINE}V39@{FG TEXT} use, you can use the following workaround:
@{lindent 16}
/* Try to get the shared semaphore */
if (!@{"AttemptSemaphoreShared" LINK "AttemptSemaphoreShared" 0}(ss))
{
        /* Check if we can get the exclusive version */
        if (!@{"AttemptSemaphore" LINK "AttemptSemaphore" 0}(ss))
        {
                /* Oh well, wait for the shared lock */
                ObtainSemaphoreShared(ss));
        }
}
:
:
@{"ReleaseSemaphore" LINK "ReleaseSemaphore" 0}(ss);
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
signalSemaphore - an initialized signal semaphore structure
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
This call is guaranteed to preserve all registers, starting with @{FG SHINE}V37@{FG TEXT} exec.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"ObtainSemaphore()" LINK "ObtainSemaphore" 0}, @{"InitSemaphore()" LINK "InitSemaphore" 0}, @{"ReleaseSemaphore()" LINK "ReleaseSemaphore" 0}, @{"AttemptSemaphore()" LINK "AttemptSemaphore" 0}, @{"ObtainSemaphoreList()" LINK "ObtainSemaphoreList" 0}, @{"Procure()" LINK "Procure" 0}, @{"Vacate()" LINK "Vacate" 0}
@ENDNODE

@NODE "OldOpenLibrary" "exec.library/OldOpenLibrary()"
@{jcenter}
@{u}@{b}OldOpenLibrary()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
OldOpenLibrary - obsolete @{"OpenLibrary()" LINK "OpenLibrary" 0}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
library = OldOpenLibrary(libName)
D0                       A1

struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33} *OldOpenLibrary(APTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
The 1.0 release of the Amiga system had an incorrect version of @{"OpenLibrary()" LINK "OpenLibrary" 0} 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" LINK "OpenLibrary" 0}(libName,0L);"
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
libName - the name of the library to open
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
library - a library pointer for a successful open, else zero
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"CloseLibrary()" LINK "CloseLibrary" 0}
@ENDNODE

@NODE "OpenDevice" "exec.library/OpenDevice()"
@{jcenter}
@{u}@{b}OpenDevice()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
OpenDevice - gain access to a device
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
error = OpenDevice(devName, unitNumber, iORequest, flags)
D0                 A0       D0          A1         D1

BYTE OpenDevice(STRPTR,ULONG,struct @{"IORequest" LINK "include:exec/io.h/MAIN" 17} *,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}NOTES@{ub}@{fg text}@{lindent 8}
All calls to OpenDevice should have matching calls to @{"CloseDevice()" LINK "CloseDevice" 0}!

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

As of @{FG SHINE}V36@{FG TEXT} 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 if you want to turn off DOS requesters.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
devName - requested device name

@{lindent 13}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.
@{lindent 8}
@{lindent 20}iORequest - the I/O request block to be returned with appropriate fields initialized.
@{lindent 8}
@{lindent 16}flags - additional driver specific information. This is sometimes used to request opening a device with exclusive access.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 16}error - Returns a sign-extended copy of the io_Error field of the @{"IORequest" LINK "include:exec/io.h/MAIN" 17}. Zero if successful, else an error code is returned.
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
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.

Prior to @{FG SHINE}V36@{FG TEXT}, 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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"CloseDevice()" LINK "CloseDevice" 0}, @{"DoIO()" LINK "DoIO" 0}, @{"SendIO()" LINK "SendIO" 0}, @{"CheckIO()" LINK "CheckIO" 0}, @{"AbortIO()" LINK "AbortIO" 0}, @{"WaitIO()" LINK "WaitIO" 0}
@ENDNODE

@NODE "OpenLibrary" "exec.library/OpenLibrary()"
@{jcenter}
@{u}@{b}OpenLibrary()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
OpenLibrary - gain access to a library
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
library = OpenLibrary(libName, version)
D0                    A1       D0

struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33} *OpenLibrary(STRPTR, ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}NOTES@{ub}@{fg text}@{lindent 8}
All calls to OpenLibrary should have matching calls to @{"CloseLibrary()" LINK "CloseLibrary" 0}!

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

As of @{FG SHINE}V36@{FG TEXT} 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 if you want to turn off DOS requesters.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
libName - the name of the library to open

version - the version of the library required.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
library - a library pointer for a successful open, else zero
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
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.

Prior to @{FG SHINE}V36@{FG TEXT}, 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 disk based library must match the version number of the library, or @{FG SHINE}V36@{FG TEXT} may fail to load it.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"CloseLibrary()" LINK "CloseLibrary" 0}
@ENDNODE

@NODE "OpenResource" "exec.library/OpenResource()"
@{jcenter}
@{u}@{b}OpenResource()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
OpenResource - gain access to a resource
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
resource = OpenResource(resName)
D0                      A1

APTR OpenResource(STRPTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This function returns a pointer to a resource that was previously installed into the system.

There is no CloseResource() function.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
resName - the name of the resource requested.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
resource - if successful, a resource pointer, else NULL
@ENDNODE

@NODE "Permit" "exec.library/Permit()"
@{jcenter}
@{u}@{b}Permit()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Permit - permit task rescheduling.
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
Permit()

void Permit(void);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Allow other tasks to be scheduled to run by the dispatcher, after a matching @{"Forbid()" LINK "Forbid" 0} has been executed.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
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" 0}.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
This call is guaranteed to preserve all registers.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"Forbid()" LINK "Forbid" 0}, @{"Disable()" LINK "Disable" 0}, @{"Enable()" LINK "Enable" 0}
@ENDNODE

@NODE "Procure" "exec.library/Procure()"
@{jcenter}
@{u}@{b}Procure()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Procure - bid for a semaphore  @{FG SHINE}(V39)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
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} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This function is used to obtain a semaphore in an async manner. Like @{"ObtainSemaphore()" LINK "ObtainSemaphore" 0}, it will obtain a @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} for you but unlike @{"ObtainSemaphore()" LINK "ObtainSemaphore" 0}, 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" 0} 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-@{FG SHINE}V39@{FG TEXT}, Procure() and @{"Vacate()" LINK "Vacate" 0} 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 @{FG SHINE}V39@{FG TEXT} will no longer work.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
@{lindent 20}semaphore - The @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} that you wish to Procure()@{lindent 8}
@{lindent 21}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, the Procure() was aborted via @{"Vacate()" LINK "Vacate" 0}. 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.
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
Before @{FG SHINE}V39@{FG TEXT}, Procure() and @{"Vacate()" LINK "Vacate" 0} used a different semaphore system that was very broken. This new system is only available as of @{FG SHINE}V39@{FG TEXT} even though the LVOs are the same.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}, @{"InitSemaphore()" LINK "InitSemaphore" 0}, @{"ReleaseSemaphore()" LINK "ReleaseSemaphore" 0}, @{"AttemptSemaphore()" LINK "AttemptSemaphore" 0}, @{"ObtainSemaphoreList()" LINK "ObtainSemaphoreList" 0}, @{"Vacate()" LINK "Vacate" 0}, @{"ObtainSemaphore()" LINK "ObtainSemaphore" 0}
@ENDNODE

@NODE "PutMsg" "exec.library/PutMsg()"
@{jcenter}
@{u}@{b}PutMsg()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
PutMsg - put a message to a message port
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
PutMsg(port, message)
       A0    A1

void PutMsg(struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} *, struct @{"Message" LINK "include:exec/ports.h/MAIN" 46} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 ReplyPort field is non-zero, when the message is replied by the receiver, it will be sent back to that port.

Any one of the following actions can be set to occur when a message is put:
@{lindent 16}
1. no special action
2. signal a given task (specified by MP_SIGTASK)
3. cause a software interrupt (specified by MP_SIGTASK)
@{lindent 8}
The action is selected depending on the value found in the MP_FLAGS of the destination port.
@{lindent 4}
@{fg shine}@{b}IMPLEMENTATION@{ub}@{fg text}@{lindent 8}
1.  Sets the LN_TYPE field to "NT_MESSAGE".
2.  Attaches the message to the destination port.
3.  Performs the specified arrival action at the destination.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
port - pointer to a message port
message - pointer to a message
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"GetMsg()" LINK "GetMsg" 0}, @{"ReplyMsg()" LINK "ReplyMsg" 0}, @{"exec/ports.h" LINK "include:exec/ports.h/MAIN" 0}
@ENDNODE

@NODE "RawDoFmt" "exec.library/RawDoFmt()"
@{jcenter}
@{u}@{b}RawDoFmt()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RawDoFmt - format data into a character stream.
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
NextData = RawDoFmt(@{"FormatString" LINK "locale.guide/FormatString" 0}, DataStream, PutChProc, PutChData);
d0                   a0            a1          a2         a3

APTR RawDoFmt(STRPTR,APTR,void (*)(),APTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.guide/FormatString" 0}, 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 @{FG SHINE}V36@{FG TEXT}, 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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{"FormatString()" LINK "locale.guide/FormatString" 0} - a "C"-language-like NULL terminated format string, with the following supported % options:

%[flags][width.limit][length]type

@{lindent 17}flags  - only one allowed. '-' specifies left justification.@{lindent 8}
@{lindent 17}width  - field width. If the first character is a '0', the field will be padded with leading 0's.@{lindent 8}
@{lindent 17}  .    - must follow the field width, if specified@{lindent 8}
@{lindent 17}limit  - maximum number of characters to output from a string. (only valid for %s).@{lindent 8}
@{lindent 17}length - size of input data defaults to WORD for types d, x, and c, 'l' changes this to long (32-bit).@{lindent 8}
@{lindent 17}type   - supported types are:@{lindent 20}
@{lindent 24}b - BSTR, data is 32-bit BPTR to byte count followed by a byte string, or NULL terminated byte string. A NULL BPTR is treated as an empty string. (Added in @{FG SHINE}V36@{FG TEXT} exec)@{lindent 20}
d - decimal
u - unsigned decimal (Added in @{FG SHINE}V37@{FG TEXT} exec)
x - hexadecimal
@{lindent 24}s - string, a 32-bit pointer to a NULL terminated byte string. In @{FG SHINE}V36@{FG TEXT}, a NULL pointer is treated as an empty string@{lindent 20}
c - character
@{lindent 8}
@{lindent 21}DataStream - a stream of data that is interpreted according to the format string. Often this is a pointer into the task's stack.@{lindent 8}
@{lindent 21}PutChProc  - the procedure to call with each character to be output, called as:
@{lindent 8}
PutChProc(Char,  PutChData);
          D0-0:8 A3
@{lindent 16}
the procedure is called with a NULL Char at the end of the format string.
@{lindent 8}
@{lindent 20}PutChData - a value that is passed through to the PutChProc procedure. This is untouched by RawDoFmt, and may be modified by the PutChProc.
@{lindent 4}
@{fg shine}@{b}EXAMPLE@{ub}@{fg text}@{lindent 8}
;
; Simple version of the C "sprintf" function.  Assumes C-style
; stack-based function conventions.
;
;   long eyecount;
;   eyecount=2;
;   @{"sprintf" LINK "amiga_lib.guide/sprintf" 0}(string,"%s have %ld eyes.","Fish",eyecount);
;
; would produce "Fish have 2 eyes." in the string buffer.
;@{lindent 16}
XDEF _sprintf
XREF _AbsExecBase
XREF _LVORawDoFmt@{lindent 8}
_sprintf:       ; ( ostring, format, {values} )@{lindent 16}
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.guide/FormatString" 0} 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
@{lindent 8}
;------ PutChProc function used by RawDoFmt -----------
stuffChar:@{lindent 16}
move.b  d0,(a3)+        ;Put data to output string
rts
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
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 @{FG SHINE}V36@{FG TEXT} and later releases of EXEC. Pre-@{FG SHINE}V36@{FG TEXT} versions of EXEC have "random" return values.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
Documentation on the C language "@{"printf" LINK "amiga_lib.guide/printf" 0}" call in any C language reference book.
@ENDNODE

@NODE "ReleaseSemaphore" "exec.library/ReleaseSemaphore()"
@{jcenter}
@{u}@{b}ReleaseSemaphore()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
ReleaseSemaphore - make signal semaphore available to others
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
ReleaseSemaphore(signalSemaphore)
                 A0

void ReleaseSemaphore(struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
ReleaseSemaphore() is the inverse of @{"ObtainSemaphore()" LINK "ObtainSemaphore" 0}. 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" 0} 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.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
signalSemaphore - an initialized signal semaphore structure
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
This call is guaranteed to preserve all registers.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"InitSemaphore()" LINK "InitSemaphore" 0}, @{"ObtainSemaphore()" LINK "ObtainSemaphore" 0}, @{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}
@ENDNODE

@NODE "ReleaseSemaphoreList" "exec.library/ReleaseSemaphoreList()"
@{jcenter}
@{u}@{b}ReleaseSemaphoreList()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
ReleaseSemaphoreList - make a list of semaphores available
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
ReleaseSemaphoreList(list)
                     A0

void ReleaseSemaphoreList(struct @{"List" LINK "include:exec/lists.h/MAIN" 19} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
ReleaseSemaphoreList() is the inverse of @{"ObtainSemaphoreList()" LINK "ObtainSemaphoreList" 0}. It releases each element in the semaphore list.

Needless to say, havoc breaks out if the task releases more times than it has obtained.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
list - a list of signal semaphores
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"ObtainSemaphoreList()" LINK "ObtainSemaphoreList" 0}
@ENDNODE

@NODE "RemDevice" "exec.library/RemDevice()"
@{jcenter}
@{u}@{b}RemDevice()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RemDevice - remove a device from the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
RemDevice(device)
          A1

void RemDevice(struct @{"Device" LINK "include:exec/devices.h/MAIN" 23} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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:
@{lindent 10}
/* 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 name;
{
struct @{"Device" LINK "include:exec/devices.h/MAIN" 23} *result;

   @{"Forbid()" LINK "Forbid" 0};
   if(result=(struct @{"Device" LINK "include:exec/devices.h/MAIN" 23} *)@{"FindName" LINK "FindName" 0}(&SysBase->@{"DeviceList" LINK "include:dos/dosextens.h/MAIN" 341},name))
       RemDevice(result);
   @{"Permit()" LINK "Permit" 0};
}
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
device - pointer to a device node
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddLibrary()" LINK "AddLibrary" 0}
@ENDNODE

@NODE "RemHead" "exec.library/RemHead()"
@{jcenter}
@{u}@{b}RemHead()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RemHead - remove the head node from a list
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
node = RemHead(list)
D0             A0

struct @{"Node" LINK "include:exec/nodes.h/MAIN" 21} *RemHead(struct @{"List" LINK "include:exec/lists.h/MAIN" 19} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.h" LINK "include:exec/lists.h/MAIN" 0}.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
This function does not arbitrate for access to the list. The calling task must be the owner of the involved list.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
list - a pointer to the target list header
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
node - the node removed or zero when empty list
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddHead()" LINK "AddHead" 0}, @{"AddTail()" LINK "AddTail" 0}, @{"Enqueue()" LINK "Enqueue" 0}, @{"Insert()" LINK "Insert" 0}, @{"Remove()" LINK "Remove" 0}, @{"RemTail()" LINK "RemTail" 0}
@ENDNODE

@NODE "RemIntServer" "exec.library/RemIntServer()"
@{jcenter}
@{u}@{b}RemIntServer()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RemIntServer - remove an interrupt server from a server chain
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
RemIntServer(intNum, interrupt)
             D0      A1

void RemIntServer(ULONG,struct @{"Interrupt" LINK "include:exec/interrupts.h/MAIN" 21} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
intNum - the Paula interrupt bit (0..14)
interrupt - pointer to an interrupt server node
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
Before @{FG SHINE}V36@{FG TEXT} Kickstart, the feature that disables the interrupt would not function. For most server chains this does not cause a problem.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddIntServer()" LINK "AddIntServer" 0}, @{"hardware/intbits.h" LINK "include:hardware/intbits.h/MAIN" 0}
@ENDNODE

@NODE "RemLibrary" "exec.library/RemLibrary()"
@{jcenter}
@{u}@{b}RemLibrary()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RemLibrary - remove a library from the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
RemLibrary(library)
           A1

void RemLibrary(struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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. Example:
@{lindent 10}
/* 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 name;
{
struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33} *result;

   @{"Forbid()" LINK "Forbid" 0};
   if(result=(struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33} *)@{"FindName" LINK "FindName" 0}(&SysBase->LibList,name))
       RemLibrary(result);
   @{"Permit()" LINK "Permit" 0};
}
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
library - pointer to a library node structure
@ENDNODE

@NODE "RemMemHandler" "exec.library/RemMemHandler()"
@{jcenter}
@{u}@{b}RemMemHandler()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RemMemHandler - Remove low memory handler from exec  @{FG SHINE}(V39)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
RemMemHandler(memHandler)
              A1

VOID RemMemHandler(struct @{"Interrupt" LINK "include:exec/interrupts.h/MAIN" 21} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
When removing a handler, the handler may be called until this function returns. Thus, the handler must still be valid until then.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
memHandler - Pointer to a handler added with @{"AddMemHandler()" LINK "AddMemHandler" 0}
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddMemHandler()" LINK "AddMemHandler" 0}, @{"exec/interrupts.h" LINK "include:exec/interrupst.h/MAIN" 0}
@ENDNODE

@NODE "Remove" "exec.library/Remove()"
@{jcenter}
@{u}@{b}Remove()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Remove - remove a node from a list
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
Remove(node)
       A1

void Remove(struct @{"Node" LINK "include:exec/nodes.h/MAIN" 21} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.h" LINK "include:exec/lists.h/MAIN" 0}.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
This function does not arbitrate for access to the list. The calling task must be the owner of the involved list.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
node - the node to remove
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddHead()" LINK "AddHead" 0}, @{"AddTail()" LINK "AddTail" 0}, @{"Enqueue()" LINK "Enqueue" 0}, @{"Insert()" LINK "Insert" 0}, @{"RemHead()" LINK "RemHead" 0}, @{"RemTail()" LINK "RemTail" 0}
@ENDNODE

@NODE "RemPort" "exec.library/RemPort()"
@{jcenter}
@{u}@{b}RemPort()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RemPort - remove a message port from the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
RemPort(port)
        A1

void RemPort(struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
port - pointer to a message port
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddPort()" LINK "AddPort" 0}, @{"FindPort()" LINK "FindPort" 0}
@ENDNODE

@NODE "RemResource" "exec.library/RemResource()"
@{jcenter}
@{u}@{b}RemResource()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RemResource - remove a resource from the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
RemResource(resource)
            A1

void RemResource(APTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This function removes an existing resource from the system resource list. There must be no outstanding users of the resource.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
resource - pointer to a resource node
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddResource()" LINK "AddResource" 0}
@ENDNODE

@NODE "RemSemaphore" "exec.library/RemSemaphore()"
@{jcenter}
@{u}@{b}RemSemaphore()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RemSemaphore - remove a signal semaphore from the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
RemSemaphore(signalSemaphore)
             A1

void RemSemaphore(struct @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
signalSemaphore - an initialized signal semaphore structure
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddSemaphore()" LINK "AddSemaphore" 0}, @{"FindSemaphore()" LINK "FindSemaphore" 0}
@ENDNODE

@NODE "RemTail" "exec.library/RemTail()"
@{jcenter}
@{u}@{b}RemTail()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RemTail - remove the tail node from a list
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
node = RemTail(list)
D0             A0

struct @{"Node" LINK "include:exec/nodes.h/MAIN" 21} *RemTail(struct @{"List" LINK "include:exec/lists.h/MAIN" 19} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.h" LINK "include:exec/lists.h/MAIN" 0}.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
This function does not arbitrate for access to the list. The calling task must be the owner of the involved list.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
list - a pointer to the target list header
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
node - the node removed or zero when empty list
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddHead()" LINK "AddHead" 0}, @{"AddTail()" LINK "AddTail" 0}, @{"Enqueue()" LINK "Enqueue" 0}, @{"Insert()" LINK "Insert" 0}, @{"Remove()" LINK "Remove" 0}, @{"RemHead()" LINK "RemHead" 0}
@ENDNODE

@NODE "RemTask" "exec.library/RemTask()"
@{jcenter}
@{u}@{b}RemTask()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
RemTask - remove a task from the system
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
RemTask(task)
        A1

void RemTask(struct @{"Task" LINK "include:exec/tasks.h/MAIN" 23} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 15}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.
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
Before @{FG SHINE}V36@{FG TEXT} if RemTask() was called on a task other than the current task, and that task was created with @{"amiga.lib/CreateTask" LINK "amiga_lib.guide/CreateTask" 0}, there was a slight chance of a crash. The problem can be hidden by bracketing RemTask() with @{"Forbid()" LINK "Forbid" 0}/@{"Permit()" LINK "Permit" 0}.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddTask()" LINK "AddTask" 0}, @{"AllocEntry()" LINK "AllocEntry" 0}, @{"amiga.lib/DeleteTask()" LINK "amiga_lib.guide/DeleteTask" 0}
@ENDNODE

@NODE "ReplyMsg" "exec.library/ReplyMsg()"
@{jcenter}
@{u}@{b}ReplyMsg()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
ReplyMsg - put a message to its reply port
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
ReplyMsg(message)
         A1

void ReplyMsg(struct @{"Message" LINK "include:exec/ports.h/MAIN" 46} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
message - a pointer to the message
@{lindent 4}
@{fg shine}@{b}IMPLEMENTATION@{ub}@{fg text}@{lindent 8}
1> Places "NT_REPLYMSG" into LN_TYPE.
@{lindent 11}2> Puts the message to the port specified by MN_REPLYPORT If there is no replyport, sets LN_TYPE to "NT_FREEMSG" (use this feature only with extreme care).
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"GetMsg()" LINK "GetMsg" 0}, @{"PutMsg()" LINK "PutMsg" 0}, @{"exec/ports.h" LINK "include:exec/ports.h/MAIN" 0}
@ENDNODE

@NODE "SendIO" "exec.library/SendIO()"
@{jcenter}
@{u}@{b}SendIO()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
SendIO - initiate an I/O command
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
SendIO(iORequest)
       A1

void SendIO(struct @{"IORequest" LINK "include:exec/io.h/MAIN" 17} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 17} will be set to zero before the request is sent. See @{"BeginIO()" LINK "serial.guide/BeginIO" 0} for more details.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 20}iORequest - pointer to an I/O request, or a device specific extended @{"IORequest" LINK "include:exec/io.h/MAIN" 17}.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"DoIO()" LINK "DoIO" 0}, @{"CheckIO()" LINK "CheckIO" 0}, @{"WaitIO()" LINK "WaitIO" 0}, @{"AbortIO()" LINK "AbortIO" 0}
@ENDNODE

@NODE "SetExcept" "exec.library/SetExcept()"
@{jcenter}
@{u}@{b}SetExcept()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
SetExcept - define certain signals to cause exceptions
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
oldSignals = SetExcept(newSignals, signalMask)
D0                     D0          D1

ULONG SetExcept(ULONG,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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:
@{lindent 12}
newExcptSet = <exceptCode>(signals, exceptData),SysBase
D0                         D0       A1          A6
@{lindent 12}
@{lindent 22}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.
@{lindent 12}
@{lindent 25}exceptData - A copy of the task structure tc_ExceptData field.
@{lindent 12}
@{lindent 26}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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 21}newSignals - the new values for the signals specified in signalMask.@{lindent 8}
signalMask - the set of signals to be effected
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
oldSignals - the prior exception signals
@{lindent 4}
@{fg shine}@{b}EXAMPLE@{ub}@{fg text}@{lindent 8}
Get the current state of all exception signals:@{lindent 12}
SetExcept(0,0)@{lindent 8}
Change a few exception signals:@{lindent 12}
SetExcept($1374,$1074)
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"Signal()" LINK "Signal" 0}, @{"SetSignal()" LINK "SetSignal" 0}
@ENDNODE

@NODE "SetFunction" "exec.library/SetFunction()"
@{jcenter}
@{u}@{b}SetFunction()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
SetFunction - change a function vector in a library
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
oldFunc = SetFunction(library, funcOffset, funcEntry)
D0                    A1       A0.W        D0

APTR SetFunction(struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33} *,LONG,APTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
If you use SetFunction on a function that can be called from interrupts, you are obligated to provide your own arbitration.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
SetFunction cannot be used on non-standard libraries like pre-@{FG SHINE}V36@{FG TEXT} dos.library. Here you must manually @{"Forbid()" LINK "Forbid" 0}, preserve all 6 original bytes, set the new vector, @{"SumLibrary()" LINK "SumLibrary" 0}, then @{"Permit()" LINK "Permit" 0}.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
library    - a pointer to the library to be changed
funcOffset - the offset of the function to be replaced
funcEntry  - pointer to new function
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
oldFunc    - pointer to the old function that was just replaced
@ENDNODE

@NODE "SetIntVector" "exec.library/SetIntVector()"
@{jcenter}
@{u}@{b}SetIntVector()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
SetIntVector - set a new handler for a system interrupt vector
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
oldInterrupt = SetIntVector(intNumber, interrupt)
D0                          D0         A1

struct @{"Interrupt" LINK "include:exec/interrupts.h/MAIN" 21} *SetIntVector(ULONG, struct @{"Interrupt" LINK "include:exec/interrupts.h/MAIN" 21} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 structure will be copied into a private place by Exec. A pointer to the previously installed Interrupt structure is returned.

When the system calls the specified interrupt code, the registers are setup as follows:
@{lindent 12}
D0 - scratch
@{lindent 17}D1 - scratch (on entry: active interrupts -> equals INTENA & INTREQ)@{lindent 12}
@{lindent 17}A0 - scratch (on entry: pointer to base of custom chips for fast indexing)@{lindent 12}
@{lindent 17}A1 - scratch (on entry: Interrupt's IS_DATA pointer)@{lindent 12}
@{lindent 17}A5 - jump vector register (scratch on call)@{lindent 12}
@{lindent 17}A6 - Exec library base pointer (scratch on call)@{lindent 12}

all other registers must be preserved
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 17}intNum - the Paula interrupt bit number (0..14). Only non-chained interrupts should be set. Use @{"AddIntServer()" LINK "AddIntServer" 0} for server chains.@{lindent 8}
@{lindent 20}interrupt - a pointer to an Interrupt structure containing the handler's entry point and data segment pointer. A 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.
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
A pointer to the prior interrupt structure which had control of this interrupt.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddIntServer()" LINK "AddIntServer" 0},@{"exec/interrupts.h" LINK "include:exec/interrupst.h/MAIN" 0},@{"hardware/intbits.h" LINK "include:hardware/intbits.h/MAIN" 0}
@ENDNODE

@NODE "SetSignal" "exec.library/SetSignal()"
@{jcenter}
@{u}@{b}SetSignal()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
SetSignal - define the state of this task's signals
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
oldSignals = SetSignal(newSignals, signalMask)
D0                     D0          D1

ULONG SetSignal(ULONG,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 21}newSignals - the new values for the signals specified in signalSet.@{lindent 8}
signalMask - the set of signals to be affected.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
oldSignals - the prior values for all signals
@{lindent 4}
@{fg shine}@{b}EXAMPLES@{ub}@{fg text}@{lindent 8}
Get the current state of all signals:@{lindent 12}
SetSignal(0L,0L);@{lindent 8}
Clear the CTRL-C signal:@{lindent 12}
SetSignal(0L,SIGBREAKF_CTRL_C);
@{lindent 8}

Check if the CTRL-C signal was pressed:
@{lindent 12}
#include <@{"libraries/dos.h" LINK "include:libraries/dos.h/MAIN" 0}>

/* Check & clear CTRL_C signal */
if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
    {
    @{"printf" LINK "amiga_lib.guide/printf" 0}("CTRL-C pressed!\n");
    }
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"Signal()" LINK "Signal" 0}, @{"Wait()" LINK "Wait" 0}
@ENDNODE

@NODE "SetSR" "exec.library/SetSR()"
@{jcenter}
@{u}@{b}SetSR()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
SetSR - get and/or set processor status register
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
oldSR = SetSR(newSR, mask)
D0            D0     D1

ULONG SetSR(ULONG, ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 16}newSR - new values for bits specified in the mask. All other bits are not effected.@{lindent 8}
mask - bits to be changed
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
oldSR - the entire status register before new bits
@{lindent 4}
@{fg shine}@{b}EXAMPLES@{ub}@{fg text}@{lindent 8}
To get the current SR:@{lindent 12}
currentSR = SetSR(0,0);@{lindent 8}
To change the processor interrupt level to 3:@{lindent 12}
oldSR = SetSR($0300,$0700);@{lindent 8}
Set processor interrupts back to prior level:@{lindent 12}
SetSR(oldSR,$0700);
@ENDNODE

@NODE "SetTaskPri" "exec.library/SetTaskPri()"
@{jcenter}
@{u}@{b}SetTaskPri()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
SetTaskPri - get and set the priority of a task
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
oldPriority = SetTaskPri(task, priority)
D0-0:8                   A1    D0-0:8

BYTE SetTaskPri(struct @{"Task" LINK "include:exec/tasks.h/MAIN" 23} *,LONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" LINK "FindTask" 0}(0); as the task pointer.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
task - task to be affected
priority - the new priority for the task
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
oldPriority - the tasks previous priority
@ENDNODE

@NODE "Signal" "exec.library/Signal()"
@{jcenter}
@{u}@{b}Signal()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Signal - signal a task
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
Signal(task, signals)
       A1    D0

void Signal(struct @{"Task" LINK "include:exec/tasks.h/MAIN" 23} *,ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 "PutMsg" 0}.

This function is safe to call from interrupts.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
task - the task to be signalled
signals - the signals to be sent
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"Wait()" LINK "Wait" 0}, @{"SetSignal()" LINK "SetSignal" 0}
@ENDNODE

@NODE "StackSwap" "exec.library/StackSwap()"
@{jcenter}
@{u}@{b}StackSwap()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
StackSwap - EXEC supported method of replacing task's stack  @{FG SHINE}(V37)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
StackSwap(newStack)
          A0

VOID StackSwap(struct @{"StackSwapStruct" LINK "include:exec/tasks.h/MAIN" 51} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 @{FG SHINE}V37@{FG TEXT}.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 19}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.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 19}newStack - The structure will now contain the old stack. This means that StackSwap(foo); StackSwap(foo); will effectively do nothing.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AddTask()" LINK "AddTask" 0}, @{"RemTask()" LINK "RemTask" 0}, @{"exec/tasks.h" LINK "include:exec/tasks.h/MAIN" 0}
@ENDNODE

@NODE "SumKickData" "exec.library/SumKickData()"
@{jcenter}
@{u}@{b}SumKickData()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
SumKickData - compute the checksum for the Kickstart delta list
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
checksum = SumKickData()
D0

ULONG SumKickData(void);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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 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" 33}. 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" 33} 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" 39} structures. The memory that these @{"MemEntry" LINK "include:exec/memory.h/MAIN" 39} structures reference will be allocated (via @{"AllocAbs()" LINK "AllocAbs" 0}) at boot time. The @{"MemEntry" LINK "include:exec/memory.h/MAIN" 39} 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 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" 39} 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 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.
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
SumKickData was introduced in the 1.2 release
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
Value to be stuffed into @{"ExecBase" LINK "include:exec/execbase.h/MAIN" 33}->KickCheckSum.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
After writing to KickCheckSum, you should push the data cache. This prevents potential problems with large copyback style caches. A call to @{"CacheClearU()" LINK "CacheClearU" 0} will do fine.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"InitResident()" LINK "InitResident" 0}, @{"FindResident()" LINK "FindResident" 0}
@ENDNODE

@NODE "SumLibrary" "exec.library/SumLibrary()"
@{jcenter}
@{u}@{b}SumLibrary()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
SumLibrary - compute and check the checksum on a library
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
SumLibrary(library)
           A1

void SumLibrary(struct @{"Library" LINK "include:exec/libraries.h/MAIN" 33} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 0}.

This call could also be periodically made by some future system-checking task.
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
library - a pointer to the library to be changed
@{lindent 4}
@{fg shine}@{b}NOTE@{ub}@{fg text}@{lindent 8}
An alert will occur if the checksum fails.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"SetFunction()" LINK "SetFunction" 0}
@ENDNODE

@NODE "SuperState" "exec.library/SuperState()"
@{jcenter}
@{u}@{b}SuperState()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
SuperState - enter supervisor state with user stack
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
oldSysStack = SuperState()
D0

APTR SuperState(void);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 22}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.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"UserState()" LINK "UserState" 0}, @{"Supervisor()" LINK "SuperVisor" 0}
@ENDNODE

@NODE "Supervisor" "exec.library/Supervisor()"
@{jcenter}
@{u}@{b}Supervisor()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Supervisor - trap to a short supervisor mode function
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
result = Supervisor(userFunc)
Rx                   A5

ULONG Supervisor(void *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}EXAMPLE@{ub}@{fg text}@{lindent 16}
;Obtain the Exception Vector base.  68010 or greater only!
MOVECtrap:      movec.l VBR,d0  ;$4e7a,$0801
                rte
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
@{lindent 19}userFunc - A pointer to a short assembly language function ending in RTE. The function has full access to the register set.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
result   - Whatever values the userFunc left in the registers.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"SuperState()" LINK "SuperState" 0}, @{"UserState()" LINK "UserState" 0}
@ENDNODE

@NODE "TypeOfMem" "exec.library/TypeOfMem()"
@{jcenter}
@{u}@{b}TypeOfMem()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
TypeOfMem - determine attributes of a given memory address
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
attributes = TypeOfMem(address)
D0                     A1

ULONG TypeOfMem(void *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" LINK "include:exec/memory.h/MAIN" 27}.)
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
address - a memory address
@{lindent 4}
@{fg shine}@{b}RESULT@{ub}@{fg text}@{lindent 8}
attributes - a long word of memory attribute flags.
If the address is not in known RAM, zero is returned.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"AllocMem()" LINK "AllocMem" 0}
@ENDNODE

@NODE "UserState" "exec.library/UserState()"
@{jcenter}
@{u}@{b}UserState()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
UserState - return to user state with user stack
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
UserState(sysStack)
          D0

void UserState(APTR);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
Return to user state with user stack, from supervisor state with user stack. This function is normally used in conjunction with the @{"SuperState()" LINK "SuperState" 0} function above.

This function must not be called from the user state.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
sysStack - supervisor stack pointer
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
This function is broken in @{FG SHINE}V33/34@{FG TEXT} Kickstart. Fixed in V1.31 setpatch.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"SuperState()" LINK "SuperState" 0}, @{"Supervisor()" LINK "Supervisor" 0}
@ENDNODE

@NODE "Vacate" "exec.library/Vacate()"
@{jcenter}
@{u}@{b}Vacate()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Vacate - release a bitMessage from @{"Procure()" LINK "Procure" 0}  @{FG SHINE}(V39)@{FG TEXT}
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
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} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This function can be used to release a semaphore obtained via @{"Procure()" LINK "Procure" 0}. 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" 0} was issued and the program no longer needs to get the semaphore and wishes to cancel the @{"Procure()" LINK "Procure" 0} request. The canceled request will be replied with the ssm_Semaphore field set to NULL. If you own the semaphore, the message was already replied and only the ssm_Semaphore field will be cleared.

NOTE: Pre-@{FG SHINE}V39@{FG TEXT}, @{"Procure()" LINK "Procure" 0} 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 @{FG SHINE}V39@{FG TEXT} will no longer work.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
@{lindent 20}semaphore - The @{"SignalSemaphore" LINK "include:exec/semaphores.h/MAIN" 39} that you wish to Vacate()@{lindent 8}
@{lindent 21}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.
@{lindent 4}
@{fg shine}@{b}BUGS@{ub}@{fg text}@{lindent 8}
Before @{FG SHINE}V39@{FG TEXT}, @{"Procure()" LINK "Procure" 0} and Vacate() used a different semaphore system that was very broken. This new system is only available as of @{FG SHINE}V39@{FG TEXT} even though the LVOs are the same.
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"ObtainSemaphoreShared()" LINK "ObtainSemaphoreShared" 0}, @{"InitSemaphore()" LINK "InitSemaphore" 0}, @{"ReleaseSemaphore()" LINK "ReleaseSemaphore" 0}, @{"AttemptSemaphore()" LINK "AttemptSemaphore" 0}, @{"ObtainSemaphoreList()" LINK "ObtainSemaphoreList" 0}, @{"Procure()" LINK "Procure" 0}, @{"ObtainSemaphore()" LINK "ObtainSemaphore" 0}
@ENDNODE

@NODE "Wait" "exec.library/Wait()"
@{jcenter}
@{u}@{b}Wait()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
Wait - wait for one or more signals
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
signals = Wait(signalSet)
D0             D0

ULONG Wait(ULONG);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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.
@{lindent 4}
@{fg shine}@{b}CAUTION@{ub}@{fg text}@{lindent 8}
This function cannot be called while in supervisor mode or interrupts! This function will break the action of a @{"Forbid()" LINK "Forbid" 0} or @{"Disable()" LINK "Disable" 0} call.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
@{lindent 20}signalSet - The set of signals for which to wait.
Each bit represents a particular signal.
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
signals - the set of signals that were active
@ENDNODE

@NODE "WaitIO" "exec.library/WaitIO()"
@{jcenter}
@{u}@{b}WaitIO()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
WaitIO - wait for completion of an I/O request
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
error = WaitIO(iORequest)
D0             A1

BYTE WaitIO(struct @{"IORequest" LINK "include:exec/io.h/MAIN" 17} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
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" 0} function. @{"Wait()" LINK "Wait" 0} will return return when any of a specified set of signal is received. This is how I/O timeouts can be properly handled.
@{lindent 4}
@{fg shine}@{b}WARNING@{ub}@{fg text}@{lindent 8}
If this @{"IORequest" LINK "include:exec/io.h/MAIN" 17} was "Quick" or otherwise finished BEFORE this call, this function drops though immediately, with no call to @{"Wait()" LINK "Wait" 0}. 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" 17} from a port, WaitIO() is the preferred method. A simple @{"Remove()" LINK "Remove" 0} would require a Disable/Enable pair!
@{lindent 4}
@{fg shine}@{b}INPUTS@{ub}@{fg text}@{lindent 8}
iORequest - pointer to an I/O request block
@{lindent 4}
@{fg shine}@{b}RESULTS@{ub}@{fg text}@{lindent 8}
@{lindent 16}error - zero if successful, else an error is returned (a sign extended copy of io_Error).
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"DoIO()" LINK "DoIO" 0}, @{"SendIO()" LINK "SendIO" 0}, @{"CheckIO()" LINK "CheckIO" 0}, @{"AbortIO()" LINK "AbortIO" 0}
@ENDNODE

@NODE "WaitPort" "exec.library/WaitPort()"
@{jcenter}
@{u}@{b}WaitPort()@{uu}@{ub}
@{jleft}@{lindent 4}
@{fg shine}@{b}NAME@{ub}@{fg text}@{lindent 8}
WaitPort - wait for a given port to be non-empty
@{lindent 4}
@{fg shine}@{b}SYNOPSIS@{ub}@{fg text}@{lindent 8}
message = WaitPort(port)
D0                 A0

struct @{"Message" LINK "include:exec/ports.h/MAIN" 46} *WaitPort(struct @{"MsgPort" LINK "include:exec/ports.h/MAIN" 27} *);
@{lindent 4}
@{fg shine}@{b}FUNCTION@{ub}@{fg text}@{lindent 8}
This function waits for the given port to become non-empty. If necessary, the @{"Wait()" LINK "Wait" 0} 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).
@{lindent 4}
@{fg shine}@{b}CAUTION@{ub}@{fg text}@{lindent 8}
More than one message may be at the port when this returns. It is proper to call the @{"GetMsg()" LINK "GetMsg" 0} 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" 0} function, then use a @{"GetMsg()" LINK "GetMsg" 0} 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.
@{lindent 4}
@{fg shine}@{b}INPUT@{ub}@{fg text}@{lindent 8}
port - a pointer to the message port
@{lindent 4}
@{fg shine}@{b}RETURN@{ub}@{fg text}@{lindent 8}
message - a pointer to the first available message
@{lindent 4}
@{fg shine}@{b}SEE ALSO@{ub}@{fg text}@{lindent 8}
@{"GetMsg()" LINK "GetMsg" 0}
@ENDNODE

@NODE "--Overview--" "SAD/--Overview--"
@{jcenter}
@{u}@{b}Simple Amiga Debugging Kernel, known as "SAD"@{uu}@{ub}
@{b}It is in EXEC starting in @{FG SHINE}V39@{FG TEXT}@{ub}


@{fg shine}@{b}-- General description --@{ub}@{fg text}
@{jleft}@{lindent 1}
   The Simple Amiga Debugging Kernel (SAD) is a set of very simple control routines stored in the Kickstart ROM that would let debuggers control the Amiga's development enviroment from the outside. These tools would make it possible to do remote machine development/debugging via just the on-board serial port.

 This set of control routines is very simple and yet completely flexible, thus making it possible to control the whole machine.

@{jcenter}
@{fg shine}@{b}-- Technical Issues --@{ub}@{fg text}
@{jleft}@{lindent 1}
   SAD will make use of the motherboard serial port that exists in all Amiga systems. The connection via the serial port lets the system be able to execute SAD without needing any of the system software up and running. (SAD will play with the serial port directly)

   With some minor changes to the Amiga hardware, an NMI-like line could be hooked up to a pin on the serial port. This would let external control of the machine and would let the external controller stop the machine no matter what state it is in. (NMI is that way)

 In order to function correctly, SAD requires the some of the EXEC CPU control functions work and that @{"ExecBase" LINK "include:exec/execbase.h/MAIN" 33} be valid. Beyond that, SAD does not require the OS to be running.

@{jcenter}
@{fg shine}@{b}-- Command Overview --@{ub}@{fg text}
@{jleft}@{lindent 1}
   The basic commands needed to operate SAD are as follows:
@{lindent 8}
Read and Write memory as byte, word, and longword.
Get the register frame address (contains all registers)
JSR to Address
Return to system operation  (return from interrupt)
@{lindent 1}
   These basic routines will let the system do whatever is needed.
   Since the JSR to address and memory read/write routines can be used to download small sections of code that could be used to do more complex things, this basic command set is thus flexible enough to even replace itself.

   Caches will automatically be flushed as needed after each write. (A call to @{"CacheClearU()" LINK "CacheClearU" 0} will be made after the write and before the command done sequence)

@{jcenter}
@{fg shine}@{b}-- Technical Command Descriptions --@{ub}@{fg text}
@{jleft}@{lindent 1}
   Since the communications with SAD is via a serial port, data formats have been defined for minimum overhead while still giving reasonable data reliability. SAD will use the serial port at default 9600 baud but the external tools can change the serial port's data rate if it wishes. It would need to make sure that it will be able to reconnect. SAD sets the baud rate to 9600 each time it is entered.  However, while within SAD, a simple command to write a WORD to the SERPER register would change the baud rate. This will remain in effect until you exit and re-enter SAD or until you change the register again. (This can be usefull if you need to transfer a large amount of data)

   All commands have a basic format that they will follow. All commands have both an ACK and a completion message.

   Basic command format is:
@{lindent 8}
@{lindent 23}SENDER:        $AF <command byte> [<data bytes as needed by command>]
@{lindent 8}
Receive:
Command ACK:  $00 <command byte>

Command Done: $1F <command byte> [<data if needed>]

Waiting: $53 $41 $44 $BF

Waiting when called from @{"Debug()" LINK "Debug" 0}:      $53 $41 $44 $3F

Waiting when in dead-end crash:        $53 $41 $44 $21
@{lindent 1}
   The data sequence will be that SAD will emit a $BF and then wait for a command. If no command is received within <2> seconds, it will emit $BF again and loop back.  (This is the "heart beat" of SAD)  When called from @{"Debug()" LINK "Debug" 0} and not the NMI hook, SAD will use $3F as the "heart beat"

   If SAD does not get a responce after <10> heartbeats, it will return to the system. (Execute an RTS or RTE as needed) This is to prevent a full hang. The debugger at the other end can keep SAD happy by sending a NO-OP command.

   All I/O in SAD times out. During the transmition of a command, if more than 2 seconds pass between bytes of data SAD will time out and return to the prompt. This is mainly to help make sure that SAD can never get into an i-loop situation.

@{jcenter}
@{fg shine}@{b}-- Data Structure Issues --@{ub}@{fg text}
@{jleft}@{lindent 1}
   While executing in SAD, you may have full access to machine from the CPU standpoint. However, this could also be a problem. It is important to understand that when entered via NMI that many system lists may be in unstable state. (NMI can happen in the middle of the @{"AllocMem" LINK "AllocMem" 0} routine or task switch, etc)

   Also, since you are doing debugging, it is up to you to determin what operations can be done and what can not be done. A good example is that if you want to write a WORD or LONG that the address will need to be even on 68000 processors. Also, if you read or write memory that does not exist, you may get a bus error. Following system structures may require that you check the pointers at each step.

   When entered via @{"Debug()" LINK "Debug" 0}, you are now running as a "task" so you will be able to assume some things about system structures. This means that you are in supervisor state and that you can assume that the system is at least not between states. However, remember that since you are debugging the system, some bad code could cause data structures to be invalid. Again, standard debugging issues are in play. SAD just gives you the hooks to do whatever you need.

   Note: When SAD prompts with $BF you will be in full disable/forbid state. When $3F prompting, SAD will only do a @{"Forbid()" LINK "Forbid" 0}. It is possible for you to then disable interrupts as needed. This is done such that it is possible to "run" the system from SAD when called with @{"Debug()" LINK "Debug" 0}.

@{jcenter}
@{fg shine}@{b}-- Data Frames and the Registers --@{ub}@{fg text}
@{jleft}@{lindent 1}
   SAD generates a special data frame that can be used to read what registers contain and to change the contents of the registers. See the entry for @{"GET_CONTEXT_FRAME" LINK "GET_CONTEXT_FRAME" 0} for more details
@{jcenter}
@{fg shine}@{b}-----------------------------------------------------------------------------@{ub}@{fg text}
@{jleft}@{lindent 1}
@{fg shine}@{b}BUGS@{lindent 4}@{ub}@{fg text}
In @{FG SHINE}V39@{FG TEXT} EXEC, the @{"WRITE_BYTE" LINK "WRITE_BYTE" 0} command was not connected and this caused all of the command numbers to be off-by-one. For example, the @{"READ_WORD" LINK "READ_WORD" 0} command is listed as command $05 but in @{FG SHINE}V39@{FG TEXT} is $04. However, the ACK of the commands are still correct.

Also, in @{FG SHINE}V39@{FG TEXT} EXEC, the @{"READ_WORD" LINK "READ_WORD" 0} command would return the wrong data.

To determin if you are in @{FG SHINE}V39@{FG TEXT} or @{FG SHINE}V40@{FG TEXT} SAD, you can issue a simple SAD command at the start of the session. By sending a @{"READ_WORD" LINK "READ_WORD" 0} command, you may either get a @{"READ_WORD" LINK "READ_WORD" 0} @{FG SHINE}(V40)@{FG TEXT} or a @{"READ_LONG" LINK "READ_LONG" 0} @{FG SHINE}(V39)@{FG TEXT} ACK'ed back. So the data stream for a safe test would be:

  Send: $AF $05 $00 $F8 $00 $00          ; Read start of ROM...
  Recv: $00 $05 ....   You have @{FG SHINE}V40@{FG TEXT} SAD
  Recv: $00 $06 ....   You have @{FG SHINE}V39@{FG TEXT} SAD

Note that you should be ready to read either 2 or 4 bytes of result depending on the ACK sent by the system.
@ENDNODE

@NODE "ALLOCATE_MEMORY" "SAD/ALLOCATE_MEMORY"
@{lindent 4}
@{b}ALLOCATE MEMORY@{ub}
@{lindent 1}
 Command:       $AF $0A
 Data:          $qq $rr $ss $tt $hh $ii $jj $kk

   Allocate a chunk of memory that is <$qqrrsstt> bytes in size. Note that this call is only safe when SAD is in $3F prompting mode (called from @{"Debug()" LINK "Debug" 0}) and even then may be unsafe if the system is in bad shape. (You are debugging after all) The returned address will be available to you until you release it. (It is obtained via a call to @{"AllocVec()" LINK "AllocVec" 0}) The type of memory allocated is <$hhiijjkk>. Note that the allocation may fail. In that case, the address returned will be $00000000.

 Command ACK:   $00 $0A
 Command DONE:  $1F $0A $ww $xx $yy $zz
@ENDNODE

@NODE "CALL_ADDRESS" "SAD/CALL_ADDRESS"
@{lindent 4}
@{b}CALL ADDRESS@{ub} - JSR to the given address.
@{lindent 1}
 Command:       $AF $07
 Data:          $ww $xx $yy $zz

   Call the following address as a subroutine. No registers will be set up but the context frame will exist. Standard calling conventions apply (d0/d1/a0/a1 are available, rest must be saved) The command will be ACK'ed when received.

 Command ACK:   $00 $07
 Command DONE:  $1F $07
@ENDNODE

@NODE "FREE_MEMORY" "SAD/FREE_MEMORY"
@{lindent 4}
@{b}FREE MEMORY@{ub}
@{lindent 1}
 Command:       $AF $0B
 Data:          $ww $xx $yy $zz

   Free the memory allocated with the ALLOCATE MEMORY command. This command has the same restrictions as ALLOCATE MEMORY. Memory is released by calling @{"FreeVec()" LINK "FreeVec" 0} on the address <$wwxxyyzz>

 Command ACK:   $00 $0B
 Command DONE:  $1F $0B
@ENDNODE

@NODE "GET_CONTEXT_FRAME" "SAD/GET_CONTEXT_FRAME"
@{lindent 4}
@{b}GET CONTEXT FRAME@{ub}
@{lindent 1}
 Command:       $AF $09
 Data:          <none>

   This command will return a pointer to the saved context. This will be a pointer to all of the registers that were saved on the stack along with some other details. Returns frame address <$wwxxyyzz>

   The pointer returned is to the following structure:

   STRUCTURE      SAD_FRAME,0@{lindent 8}
; The first three are READ-ONLY...  Mainly used to make it
; easier to understand what is going on in the system.
ULONG   SAD_VBR         ; Current VBR (always 0 on 68000 CPUs)
ULONG   SAD_AttnFlags   ; ULONG copy of the flags (UPPER WORD==0)
ULONG   SAD_ExecBase    ; @{"ExecBase" LINK "include:exec/execbase.h/MAIN" 33}
; These fields are the user registers...  The registers are
; restored from these fields on exit from SAD...
; Note that USP is only valid if SR was *NOT* supervisor...
ULONG   SAD_USP         ; User stack pointer
ULONG   SAD_D0          ; User register d0
ULONG   SAD_D1          ; User register d1
ULONG   SAD_D2          ; User register d2
ULONG   SAD_D3          ; User register d3
ULONG   SAD_D4          ; User register d4
ULONG   SAD_D5          ; User register d5
ULONG   SAD_D6          ; User register d6
ULONG   SAD_D7          ; User register d7
ULONG   SAD_A0          ; User register a0
ULONG   SAD_A1          ; User register a1
ULONG   SAD_A2          ; User register a2
ULONG   SAD_A3          ; User register a3
ULONG   SAD_A4          ; User register a4
ULONG   SAD_A5          ; User register a5
ULONG   SAD_A6          ; User register a6
; This is for SAD internal use...  It is the prompt that
; SAD is using...  Changing this will have no effect on SAD.
ULONG   SAD_PROMPT      ; SAD Prompt Longword...  (internal use)
; From here on down is the standard exception frame
; The first two entries (SR and PC) are standard on all 680x0 CPUs
UWORD   SAD_SR          ; Status register (part of exception frame)
ULONG   SAD_PC          ; Return address (part of exception frame)

@{lindent 1}
 Command ACK:   $00 $09
 Command DONE:  $1F $09 $ww $xx $yy $zz
@ENDNODE

@NODE "NOP" "SAD/NOP"
@{lindent 4}
@{b}NO-OP@{ub} - Do nothing other than tell SAD you are still there...
@{lindent 1}
 Command:       $AF $00
 Data:          <none>

   This just tells SAD you are still there. Required so that timeouts do not exit SAD while you are not doing anything.

 This command will *NOT* be ACK'ed. It will just cause the timeout to be restarted.
@ENDNODE

@NODE "READ_ARRAY" "SAD/READ_ARRAY"
@{lindent 4}
@{b}READ ARRAY@{ub} - Read a range of bytes
@{lindent 1}
 Command:       $AF $0F
 Data:          $ww $xx $yy $zz $qq $rr $ss $tt

   Read a range of bytes from address <$wwxxyyzz> for <$qqrrsstt> bytes Will return that number of bytes...

 Command will be ACK'ed when received.

 Command ACK:   $00 $0F
 Command DONE:  $1F $0F $uu [$uu ...]
@ENDNODE

@NODE "READ_BYTE" "SAD/READ_BYTE"
@{lindent 4}
@{b}READ BYTE@{ub} - Read a byte from the given address
@{lindent 1}
 Command:       $AF $04
 Data:          $ww $xx $yy $zz

 Read a byte from address <$wwxxyyzz>  Returns <$qq> as result

 Command will be ACK'ed when received.

 Command ACK:   $00 $04
 Command DONE:  $1F $04 $qq
@ENDNODE

@NODE "READ_LONG" "SAD/READ_LONG"
@{lindent 4}
@{b}READ LONG@{ub} - Read a long from the given address
@{lindent 1}
 Command:       $AF $06
 Data:          $ww $xx $yy $zz

 Read a long from address <$wwxxyyzz>  Returns <$qqrrsstt> as result

 Command will be ACK'ed when received.

 Command ACK:   $00 $06
 Command DONE:  $1F $06 $qq $rr $ss $tt
@ENDNODE

@NODE "READ_WORD" "SAD/READ_WORD"
@{lindent 4}
@{b}READ WORD@{ub} - Read a word from the given address  @{FG SHINE}(V40 SAD)@{FG TEXT}
@{lindent 1}
 Command:       $AF $05
 Data:          $ww $xx $yy $zz

 Read a word from address <$wwxxyyzz>  Returns <$qqrr> as result

 Command will be ACK'ed when received.

 Command ACK:   $00 $05
 Command DONE:  $1F $05 $qq $rr
@{lindent 4}
@{fg shine}@{b}BUGS@{lindent 8}@{ub}@{fg text}
This command does not return correct values in pre-@{FG SHINE}V40@{FG TEXT} EXEC.
@ENDNODE

@NODE "RESET" "SAD/RESET"
@{lindent 4}
@{b}RESET@{ub} - Reset the computer...
@{lindent 1}
 Command:       $AF $10
 Data:          $FF $FF $FF $FF

   This command will reset the computer. The $FFFFFFFF value is there mainly to prevent false reset. This command will only be ACK'ed as the computer will be reset afterwards...

 Command will be ACK'ed when received.

 Command ACK:   $00 $10
@ENDNODE

@NODE "RETURN_TO_SYSTEM" "SAD/RETURN_TO_SYSTEM"
@{lindent 4}
@{b}RETURN TO SYSTEM@{ub}
@{lindent 1}
 Command:       $AF $08
 Data:          $00 $00 $00 $00

   This command will return <exit> from SAD back to whatever started it. The 4 $00 are required as a "safty" to this command. The command will be ACK'ed only as it will have lost control of the system.

 Command ACK:   $00 $08
@ENDNODE

@NODE "TURN_OFF_SINGLE" "SAD/TURN_OFF_SINGLE"
@{lindent 4}
@{b}TURN OFF SINGLE STEPPING@{ub}
@{lindent 1}
 Command:       $AF $0D
 Data:          $ww $xx $yy $zz

   This command will turn off SAD single stepping mode. You need to pass to it the address returned from the call to turn on single stepping mode.

 Command ACK:   $00 $0D
 Command DONE:  $1F $0D
@ENDNODE

@NODE "TURN_ON_SINGLE" "SAD/TURN_ON_SINGLE"
@{lindent 4}
@{b}TURN ON SINGLE STEPPING@{ub}
@{lindent 1}
 Command:       $AF $0C
 Data:          <none>

   This command will turn on SAD single stepping mode. This means that SAD will single step (via 68000 trace mode) the system. SAD will take over the TRACE exception vector during this time. This command will return the contents of the vector such that you can return this value when you wish to turn off single stepping mode. Note that turning on single stepping mode while in $BF prompting will cause the step to be taken and then SAD will execute in $3F mode (non-NMI)
   The command returns <$wwxxyyzz> which you must use when turning off the single-step mode.

 Command ACK:   $00 $0C
 Command DONE:  $1F $0C $ww $xx $yy $zz
@ENDNODE

@NODE "WRITE_ARRAY" "SAD/WRITE_ARRAY"
@{lindent 4}
@{b}WRITE ARRAY@{ub} - Write a range of bytes
@{lindent 1}
 Command:       $AF $0E
 Data:          $ww $xx $yy $zz $qq $rr $ss $tt

   Write a range of bytes to address <$wwxxyyzz> for <$qqrrsstt> bytes After the computer sends the ACK, you must then send the byte stream...

 Command will be ACK'ed when received.

 Command ACK:   $00 $0E
 Command DONE:  $1F $0E
@ENDNODE

@NODE "WRITE_BYTE" "SAD/WRITE_BYTE"
@{lindent 4}
@{b}WRITE BYTE@{ub} - Write the given data to the address given @{FG SHINE}(V40 SAD)@{FG TEXT}
@{lindent 1}
 Command:       $AF $01
 Data:          $ww $xx $yy $zz $qq

 Write the byte <$qq> to address <$wwxxyyzz>

 Command will be ACK'ed when received.
 Command ACK:   $00 $01
 Command DONE:  $1F $01
@{lindent 4}
@{fg shine}@{b}BUGS@{lindent 8}@{ub}@{fg text}
This command does not exists in pre-@{FG SHINE}V40@{FG TEXT} EXEC.
This command can be emulated with the @{"WRITE_ARRAY" LINK "WRITE_ARRAY" 0} command with a length of 1.
@ENDNODE

@NODE "WRITE_LONG" "SAD/WRITE_LONG"
@{lindent 4}
@{b}WRITE LONG@{ub} - Write the given data to the address given
@{lindent 1}
 Command:       $AF $03
 Data:          $ww $xx $yy $zz $qq $rr $ss $tt

 Write the long <$qqrrsstt> to address <$wwxxyyzz>

 Command will be ACK'ed when received.

 Command ACK:   $00 $03
 Command DONE:  $1F $03
@ENDNODE

@NODE "WRITE_WORD" "SAD/WRITE_WORD"
@{lindent 4}
@{b}WRITE WORD@{ub} - Write the given data to the address given
@{lindent 1}
 Command:       $AF $02
 Data:          $ww $xx $yy $zz $qq $rr

 Write the word <$qqrr> to address <$wwxxyyzz>

 Command will be ACK'ed when received.

 Command ACK:   $00 $02
 Command DONE:  $1F $02
@ENDNODE
