/*** README.lwt-0.2 ***************************/ /* * Copyright (C) 1998,1999 John Haskins, Jr. */ /*********************************************/ This file (in lieu of appropraite manual pages) explains the functions in the LWT 0.2 API. It is broken into several sections which describe different elements of the API. The sections and the function names described therein are listed below: Thread Manipulation ------------------- lwt_create() lwt_kill() lwt_schedule() LWT Operation ------------- lwt_dispatcher() lwt_init() lwt_shutdown() Mutex Locks ----------- lwt_mutexinit() lwt_mutexlock() lwt_mutextest() lwt_mutexunlock() Condition Variables ------------------- lwt_conditioninit() lwt_conditionwait() lwt_conditionsignal() lwt_conditionbroadcast() Semaphores ---------- lwt_semainit() lwt_semap() lwt_semav() ============================================================================== Thread Manipulation... ============================================================================== int lwt_create(void (*funcptr)(),int stacksize,void * arg) lwt_create() creates a new user-level thread in LWT's space. The first argument (funcptr) is a pointer to a function that returns type 'void *'; the second parameter (stacksize) is an integer, specifying the amount of stack space that should be assigned to the new thread; the third parameter (arg) is a void pointer to a single argument to be passed to the thread function; (this value shoul be NULL if the thread function takes no parameter. The integer returned by lwt_create(), if greater than or equal to zero, it the new thread's thread id (tid) number. The tid is useful when calling the lwt_kill() function, to specify the thread to be killed. If the integer returned is negative, an error occured. Error codes are listed below: -EMAX means that the maximum number of threads have been allocated and the attempt to create another has failed. -ENOSTACK means that an error occurred while attempting to allocate space for the new thread's stack -ENOMEM means that an error occurred while attempting to allocate space for the new thread's data structure in LWT's space. -- void lwt_kill(int tid) lwt_kill() premanently removes a thread from the run queue. Its parameter (tid) is an integer which is the thread id number of the thread to kill. -- void lwt_schedule(void) lwt_schedule() forces a thread context scwith. The calling thread's context is stored in LWT's space and a new thread is selected automatically from the collecetion of other threads in LWT's space. If no other threads exist or LWT's 'uninterruptible' mutex is locked, the current thread is allowed to run for another quantum. -- ============================================================================== LWT Operation... ============================================================================== void lwt_dispather(int sched, int quantum) lwt_dispatcher() initializes LWT's dispatcher. It's first parameter (sched) takes one of two values, which is the scheduling policy: RR_TS, causes the dispatcher to utilize its time-slicing round-roubin algorithm. Thread switches can be explicitly called using lwt_schedule(), but also occur automatically at the expiration of thread quantums. FIFO, causes the dispatcher to utilize its first-in, first-out algorithm. All thread context switches must be explicitly called from the program using lwt_schedule() or will occur after a thread exits. The second parameter (quantum) establishes the time (in milliseconds) of each quantum wherein a thread may execute before interruption. If the scheduling policy is first-in, first-out (FIFO), this second parameter is ignored. -- void lwt_init(void) lwt_init() takes a snapshot of the location to which a thread should return when the LWT session is ended (by lwt_shutdown()). For that reason, lwt_init() must be bound within an if() statement. See the example below: if (lwt_init()) { // stuff to do just before ending program... } else { // stuff to do after taking snapshot... lwt_shutdown(); } -- void lwt_shutdown(void) lwt_shutdown() returns to the location snapshot captured by lwt_init(). See the example below: if (lwt_init()) { // stuff to do just before ending program... } else { // stuff to do after taking snapshot... lwt_shutdown(); } ============================================================================== Mutex Locks... ============================================================================== void lwt_mutexinit(mutex_t * mutex) lwt_mutexinit() initializes a mutex variable for use with LWT's mutex functions. Its parameter (mutex) is a pointer to a mutex variable. -- int lwt_mutextest(mutex_t * mutex) lwt_mutextest() tests a mutex variable. It returns zero if the mutex variable is not locked; it returns one if the mutex variable is locked. Its parameter (mutex) is a pointer to a mutex variable. -- void lwt_mutexlock(mutex_t * mutex) lwt_mutexlock() locks a mutex variable. If the mutex variable is already locked, the calling thread will be suspended and another thread selected for execution. When the calling thread receives another quantum, the lock attempt is repeated. This cycle continues ad infinitum until the calling thread is able to lock the mutex. Its parameter is a pointer to a mutex variable. -- void lwt_mutexunlock(mutex_t * mutex) lwt_mutexunlock() unlocks a mutex variable. Its parameter is a pointer to a mutex variable. ============================================================================== Condition Variables... ============================================================================== void lwt_conditioninit(cond_t * cond) lwt_conditioninit() initializes a condition variable for use with LWT's condition variable functions. Its parameter is a pointer to a condition variable. -- void lwt_conditionwait(cond_t * cond,mutex_t * mutex) lwt_conditionwait() atomically releases the mutex specified in the second parameter (mutex, a pointer to a mutex variable) and removes the calling function from its run state, blocking on the first variable (cond, a pointer to a condition variable) where it will wait it is awakened by lwt_conditionsignal() or lwt_conditionbroadcast(). -- void lwt_conditionsignal(cond_t * cond) lwt_conditionsignal() searches through LWT's threads until it finds a thread blocked on its parameter (cond, a pointer to a condition variable). If one such thread is found, lwt_conditionsignal() reinstates its runnable status and returns; if not, lwt_conditionsignal() simply returns. -- void lwt_conditionbroadcast(cond_t * cond) lwt_conditionbroadcast() searches through LWT's threads looking for threads blocked on its parameter (cond, a pointer to a condition variable). The runnable status of all such threads is reinstatesd and lwt_conditionbroadcast() returns; if no such threads are found, lwt_conditionboradcast() simply returns. ============================================================================== Semaphores... ============================================================================== void lwt_semainit(sema_t * sema) lwt_semainit() initializes a semaphore variable for use with LWT's semaphore functions. It's parameter (sema) is a pointer to a semaphore variable. -- void lwt_semap(sema_t * sema) lwt_semap() attempts to acquire the semaphore specified in its parameter (sema, a pointer to a semaphore variable). If the semaphore is already held by another thread, the calling thread is suspended and another selected to run; the calling thread may be later awakened by a subsequent call to lwt_semav(). -- void lwt_semav(sema_t * sema) lwt_semav() releases the semaphore specified in its parameter (sema, a pointer to a semaphore variable), previously locked by another thread's call to lwt_semap().