/* * thread.h * * [Generated from thread, 25 September 1996] */ #if !defined(__CC_NORCROFT) || !defined(__arm) #error You must use the Norcroft ARM Compiler for Sapphire programs #endif #pragma include_only_once #pragma force_top_level #ifndef __thread_h #define __thread_h #ifndef __sapphire_h #include "sapphire.h" #endif /*----- Overview ----------------------------------------------------------* * * Functions provided: * * thread_create * thread_setPriority * thread_setTimeSlice * thread_destroy * thread_suspend * thread_resume * thread_yield * thread_createSem * thread_destroySem * thread_threaded * thread_wait * thread_signal * thread_init * thread_enterCrit * thread_leaveCrit * thread_errorHandler */ /* --- thread_create --- * * * On entry: R0 == size of stack to allocate, or 0 for a default * R1 == pointer to thread routine * R2 == workspace pointer to pass in R10 * R3 == workspace pointer to pass in R12 * * On exit: R0 == thread handle for the thread * May return an error * * Use: Creates a new thread running `in the background' (i.e. over * idle events). * * The thread is passed control with the registers R10 and R12 * set up from R1 and R2 passed to this routine and R13 pointing * to the top of a stack chunk. R0 on entry contains the * thread's handle. The thread is passed the scratchpad * address (in R11). The values of other registers are * indeterminate and must not be relied upon. * * The default stack size for a new thread is 1K, although this * may change in future. * * The thread may exit by calling thread_destroy or by * returning in the normal way. */ extern routine thread_create; /* --- thread_setPriority --- * * * On entry: R0 == thread handle * R1 == new priority to set * * On exit: -- * * Use: Changes the priority of a thread. The priority if a thread * is a signed integer. The highest priority thread is the one * which runs. If more than one thread has maximum priority, * they are run in a cyclical order. */ extern routine thread_setPriority; /* --- thread_setTimeSlice --- * * * On entry: R0 == thread handle * R1 == new timeslice size, in centiseconds * * On exit: -- * * Use: Changes a thread's timeslice size. Specify 0 to indicate * that thread shouldn't be pre-empted. */ extern routine thread_setTimeSlice; /* --- thread_destroy --- * * * On entry: R0 == thread handle to destroy, if not executing a thread * * On exit: -- * * Use: Destroys either the current thread or a thread with the * the given handle if no thread is executing currently. You * can't destroy an arbitrary thread while running in one. * * If a thread is waiting for a semaphore, it is removed from * the waiting list. */ extern routine thread_destroy; /* --- thread_suspend --- * * * On entry: R0 == thread handle, or 0 for the current thread * * On exit: -- * * Use: Suspends a thread's execution. If a thread is currently * running, that thread is suspended. Otherwise, any thread * may be suspended. * * If the thread is currently claiming semaphores, the * semaphores are not released, because we don't whether the * system is in a fit state for this. * * Thread suspensions are counted. i.e. if you suspend a thread * 5 times, you have to resume it 5 times for it to become * active again. */ extern routine thread_suspend; /* --- thread_resume --- * * * On entry: R0 == thread handle * * On exit: -- * * Use: Allows a suspended thread to continue operations. If you * resume a thread more times than it has been suspended, * any excess resumes are ignored. You can't resume a thread * to stop it being blocked by a semaphore. */ extern routine thread_resume; /* --- thread_yield --- * * * On entry: -- * * On exit: -- * * Use: Pauses the thread for a while. You only need to use this * call if you have stopped the current thread from being * timesliced. */ extern routine thread_yield; /* --- thread_createSem --- * * * On entry: R0 == initial value for semaphore (0 for counter, 1 for * mutex) * * On exit: R0 == semaphore handle and V clear if all went well * R0 == pointer to error and V set if something went wrong * * Use: Creates a semaphore with the given initial counter value. * * The semaphore can be used to provide serialised access to * a resource by initialising its value to 1 and performing the * following: * * thread_wait(mySemaphore) * // * // Do things with the resource * // * thread_signal(mySemaphore) * * Or you can inform a thread that it has items in its input * queue by having the following in the thread code: * * while true * thread_wait(theSemaphore) * getFromQueue(myQueue,item) * process(item) * endWhile * * and when inserting queue items: * * addToQueue(item) * thread_signal(theSemaphore) * * It is distinctly possible that input queue management will * be introduced in a separate Sapphire module. */ extern routine thread_createSem; /* --- thread_destroySem --- * * * On entry: R0 == semaphore handle * * On exit: -- * * Use: Destroys a semaphore when it's no use any more. If threads * are waiting for it, an error is generated. */ extern routine thread_destroySem; /* --- thread_threaded --- * * * On entry: -- * * On exit: CS if currently running a thread, CC otherwise * * Use: Informs the caller whether a thread is currently executing. */ extern routine thread_threaded; /* --- thread_wait --- * * * On entry: R0 == semaphore handle * * On exit: If successful, R0 preserved and V clear. * If failed, R0 == pointer to error block and V set * * Use: Waits on a sempahore. The algorithm actually is as follows: * * if semaphore.counter == 0 then * addToWaitingList(semaphore,currentThread) * suspend(currentThread) * else * semaphore.counter -= 1 * endIf * * See thread_createSem for suggestions on how to make use of * semaphores. */ extern routine thread_wait; /* --- thread_signal --- * * * On entry: R0 == semaphore handle * * On exit: -- * * Use: Increments a semaphore's counter if no threads are waiting * for it, or releases a thread waiting for the semaphore. * * The actual algorithm is shown below: * * if semaphore.waitingList != 0 then * thread = removeFromWaitingList(semaphore) * unSuspend(thread) * else * semaphore.counter += 1; * endif * * See thread_createSem for suggestions on how to make use of * semaphores. */ extern routine thread_signal; /* --- thread_init --- * * * On entry: -- * * On exit: -- * * Use: Initialises the thread system for use. */ extern routine thread_init; /* --- thread_enterCrit --- * * * On entry: -- * * On exit: -- * * Use: Declares that the current thread is about to enter a * critical section and must not be interrupted. */ extern routine thread_enterCrit; /* --- thread_leaveCrit --- * * * On entry: -- * * On exit: -- * * Use: Declares that the current thread has left the critical * section and can be interrupted again. */ extern routine thread_leaveCrit; /* --- thread_errorHandler --- * * * On entry: R0 == pointer to routine to call * R1 == R12 value to call with * R2 == R13 value to call with * * On exit: -- * * Use: Sets up the error handler for a thread. */ extern routine thread_errorHandler; /*----- That's all, folks -------------------------------------------------*/ #endif