LINUX: afs_create infinite fetchStatus loop
[pkg-k5-afs_openafs.git] / src / WINNT / client_osi / libosi.rtf
blobd95875f02fd32efcdcf92b634d4c6c5a804ae387
1 {\rtf1\ansi
3 {\fonttbl
4 \f0\froman Times New Roman;
5 \f1\fdecor Courier New;}
7 {\colortbl
8 \red0\green0\blue0;
9 \red255\green0\blue0;
10 \red0\green0\blue255;
11 \red255\green255\blue0;}
13 \deff0
15 \sb200
17 #{\footnote contents}
18 ${\footnote Contents}
19 \fs40
20 {\uldb Introduction}{\v intro}
21 \par
22 {\uldb Initialization}{\v init}
23 \par
24 {\uldb Mutexes}{\v mutexes}
25 \par
26 {\uldb ReadWrite Locks}{\v rwlocks}
27 \par
28 {\uldb Condition Variables}{\v conds}
29 \par
30 {\uldb Locking Hierarchies}{\v hierarchies}
31 \par
32 {\uldb Debugging}{\v debug}
33 \par
34 \fs25
35 \page
37 #{\footnote intro}
38 ${\footnote Introduction}
39 +{\footnote intro:01}
41 The OSI package provides very efficient locking and synchronization 
42 primitives for the Win32 environment.
43 \par
45 These primitives include both {\uldb mutexes}{\v mutexes}, representing 
46 resources that must always be allocated exclusively to one entity 
47 (thread) at a time, as well as {\uldb read/write locks}{\v rwlocks}, 
48 representing resources that may have N readers or one writer at any 
49 given time.
50 \par
52 In addition to the basic primitives sketched above, the OSI package 
53 provides a {\uldb condition variable}{\v conds} mechanism that allows a 
54 thread holding a mutex or a read/write lock to wait for an interesting 
55 event to occur.  These condition variable operations allow a thread 
56 holding a resource to atomically suspend itself (sleep) and 
57 simultaneously release the lock or mutex it holds on the resource.  The 
58 atomicity of these operations is critical to avoiding race conditions.  
59 A function is also provided to wakeup a thread waiting at a condition
60 variable. 
61 \par
63 Some support is also provided for aiding programs in initializing 
64 themselves safely in a multi-threaded environment.
65 \par
67 Finally, an optional remote debugging and statistics gathering interface 
68 is provided.  If desired, the locks and mutexes provided by the OSI 
69 package can keep track of statistics on lock contention, and these 
70 statistics are available to remote users to examine, using the osidebug
71 program. 
72 \par
74 \page
76 #{\footnote init}
77 ${\footnote Initialization}
78 +{\footnote init:01}
80 There are two sets of routines describe herein, one used for 
81 initializing the 
82 OSI package itself, and one for initializing your application. 
83 \par
84 The function {\uldb osi_Init}{\vosiInit} must be called before any other 
85 functions in the OSI library, except for the other initialization 
86 functions described in this section (osi_Init, osi_InitDebug, osi_Once 
87 and osi_TestOnce).
88 \par
90 The function {\uldb osi_InitDebug} must be called before remote 
91 debugging information and statistic can be retrieved via RPC by the 
92 osidebug program.  This function need not be ever called, however, if 
93 you do not need to be able to retrieve locking information from a 
94 separate process. 
95 \par
97 The function {\uldb osi_Once}{\v osiOnce} can be used by the application 
98 programmer to ensure that the application program executes its 
99 initialization code exactly once.  This function takes one parameter, 
100 intended to be allocated as a static variable, which will be initialized 
101 by the system at load time to zero.  The {\uldb osi_Once}{\v osiOnce} 
102 function is called with a pointer to this variable, and returns TRUE if 
103 the program should execute its initialization code now, or FALSE if 
104 osi_Once has already been executed once in this application already. 
105 \par
107 The function {\uldb osi_EndOnce}{\v osiEndOnce} must be called before 
108 other calls to {\uldb osi_Once}{\v osiOnce} will complete; the section 
109 of code bounded by osi_Once and osi_EndOnce is executed atomically with 
110 respect to other calls to osi_Once. 
111 \par
113 The function {\uldb osi_TestOnce}{\v osiTestOnce} may be used as a hint 
114 to see if {\uldb osi_Once}{\v osiOnce} might need to be called.  It 
115 returns the same values as osi_Once, but doesn't change the state of the 
116 state variable to indicate that {\uldb osi_Once}{\v osiOnce} has been 
117 called.  Of course, its result can only be used as a hint, but if {\uldb 
118 osi_TestOnce}{\v osiTestOnce} returns false, the caller knows that the 
119 initialization work for this code has already run.  If it returns true, 
120 the programmer may still need to call osi_Once, or it may be called by 
121 some other thread first.
122 \par
124 \page
126 #{\footnote osiInit}
127 ${\footnote osi_Init}
128 K{\footnote osi_Init}
129 +{\footnote init:02}
131 \fs40
132 void \cf2 osi_Init\cf0 (void)
133 \fs25
134 \par
136 This function initializes the OSI library.  It must be called before any 
137 other functions in the OSI library except the other initialization 
138 calls: osi_InitDebug, osi_Once, osi_EndOnce and osi_TestOnce.
139 \par
141 Failure to call this function will result in traps in your application 
142 program.
143 \par
145 \page
147 #{\footnote osiInitDebug}
148 ${\footnote osi_InitDebug}
149 K{\footnote osi_InitDebug}
150 +{\footnote init:03}
152 \fs40
153 long \cf2 osi_InitDebug \cf0 (char *rpcName)
154 \fs25
155 \par
157 This function initializes the RDC debugging interface in your 
158 application.  The parameter rpcName is an RPC NSI name into which your 
159 RPC binding information will be exported.  It must start with the string 
160 "/.:/"  For example, a database server for your payroll database might 
161 export its binding information into "/.:/payroll"
162 \par
164 The function returns 0 if it succeeds, otherwise it returns an RPC error 
165 code. 
166 \par
168 \page
170 #{\footnote osiOnce}
171 ${\footnote osi_Once}
172 K{\footnote osi_Once}
173 +{\footnote init:04}
175 \fs40
176 int \cf2 osi_Once \cf0 (osi_once_t *parm)
177 \fs25
178 \par
180 This function can be used by application programs in a multi-threaded 
181 environment to ensure that they execute their initialization code 
182 exactly once, no matter how many threads try to execute the code.
183 \par
185 int foo_Init(void) \line
186 \{ \line
187     static osi_once_t once; \line
188     if (osi_Once(&once)) \{ \line
189         YourInitializationHere = 1; \line
190         osi_EndOnce(&once); \line
191     \} \line
192     return SUCCESS; \line
193 \} \line
195 \par
197 In the above function, the assignment into YourInitializationHere will 
198 occur exactly once, no matter how many times foo_Init is called, in any 
199 number of threads, all calling foo_Init concurrently.
201 \page
203 #{\footnote osiEndOnce}
204 ${\footnote osi_EndOnce}
205 K{\footnote osi_EndOnce}
206 +{\footnote init:05}
208 \fs40
209 void \cf2 osi_EndOnce \cf0 (osi_once_t *parm)
210 \fs25
211 \par
213 This function ends the initialization block started by osi_Once.  This 
214 function must be called exactly once for each call to osi_Once that 
215 returns true.
216 \par
217 An example of the use of this function can be found in the description 
218 of {\uldb osi_Once}{\v osiOnce}.
220 \page
222 #{\footnote osiTestOnce}
223 ${\footnote osi_TestOnce}
224 K{\footnote osi_TestOnce}
225 +{\footnote init:06}
227 \fs40
228 int \cf2 osi_TestOnce \cf0 (osi_once_t *parm)
229 \fs25
230 \par
232 This function returns true if osi_Once would have returned true, and 
233 false otherwise.
234 \par
236 Unlike osi_Once, this function does not mark the initialization block 
237 described by *parm as initialized; this is only an advisory function.  
238 For this reason, the function {\uldb osi_EndOnce}{\v osiEndOnce} should 
239 not be called if osi_TestOnce returns true. 
241 \page
243 #{\footnote mutexes}
244 ${\footnote Mutual Exclusion Objects}
245 +{\footnote mutexes:01}
247 Mutual exclusion objects are used to prevent two threads from accesing 
248 the same object at the same time.  Typically, some collection of data 
249 is associated with an object of osi_mutex_t, and any thread, before 
250 accessing the object, first obtains the mutex by calling {\uldb
251 lock_ObtainMutex}{\v lockObtainMutex}.  When it is done processing the 
252 object, the thread calls {\uldb lock_ReleaseMutex}{\v lockReleaseMutex}. 
253 \par
255 Typically, a thread will release a mutex once for each time that it  
256 obtains the mutex, using {\uldb osi_SleepM}{\v osiSleepM} or 
257 {\uldb lock_ReleaseMutex}{\v lockReleaseMutex}. 
258 \par
260 These mutex objects are not recursive mutexes: a thread may not 
261 re-obtain the mutex while still holding it.
262 \par
264 Before using a mutex, the mutex \cf1 must \cf0 be initialized by calling 
265 {\uldb lock_InitializeMutex}{\v lockInitializeMutex}.
266 \par
268 If the mutex is allocated from dynamically allocated memory (rather than 
269 being statically allocated), then the mutex must be finalized before 
270 the memory is freed.  The function 
271 {\uldb lock_FinalizeMutex}{\v lockFinalizeMutex} should be used for this 
272 purpose.
273 \par
275 An object of type osi_mutex_t uses about 8 bytes of storage.
276 \par
278 \page
280 #{\footnote lockInitializeMutex}
281 ${\footnote lock_InitializeMutex}
282 K{\footnote lock_InitializeMutex}
283 +{\footnote mutexes:02}
285 \fs40
286 void \cf2 lock_InitializeMutex \cf0 (osi_mutex_t *mutex)
287 \fs25
288 \par
290 This function is called with a pointer to a mutex, to initialize the storage 
291 so that the mutex can be obtained and released by this or other threads. 
292 This function should only be called at an initialization point where the 
293 programmer knows that no other threads are accessing the mutex variable.
294 \par
296 \page
298 #{\footnote lockObtainMutex}
299 ${\footnote lock_ObtainMutex}
300 K{\footnote lock_ObtainMutex}
301 +{\footnote mutexes:03}
303 \fs40
304 void \cf2 lock_ObtainMutex \cf0 (osi_mutex_t *mutex)
305 \fs25
306 \par
308 This function is called with a pointer to a mutex, 
309 and waits until no other thread is using the mutex.  It then 
310 obtains the mutex for the calling thread and returns.
311 \par
313 Mutexes are not recursively obtainable by a thread: if a thread tries 
314 to obtain a mutex a second time, it will deadlock (wait forever). 
315 \par
317 The mutex can be released {\uldb lock_ReleaseMutex}{\v lockReleaseMutex} 
318 or by {\uldb osi_SleepM}{\v osiSleepM}.
319 \par
321 \page
323 #{\footnote lockReleaseMutex}
324 ${\footnote lock_ReleaseMutex}
325 K{\footnote lock_ReleaseMutex}
326 +{\footnote mutexes:04}
328 \fs40
329 void \cf2 lock_ReleaseMutex \cf0 (osi_mutex_t *mutex)
330 \fs25
331 \par
333 This function relinquishes the caller's use of the resource; if any other threads 
334 are waiting for the mutex, they are woken at this point, and one of the other 
335 threads is given the mutex.
336 \par
338 It is an error to release a mutex twice.  However, a mutex can be released by a different 
339 thread than that which obtained it, as long as this is the programmer's intention.
340 \par
342 \page
344 #{\footnote lockFinalizeMutex}
345 ${\footnote lock_FinalizeMutex}
346 K{\footnote lock_FinalizeMutex}
347 +{\footnote mutexes:05}
349 \fs40
350 void \cf2 lock_FinalizeMutex \cf0 (osi_mutex_t *mutex)
351 \fs25
352 \par
354 This function is used to free up any auxiliary storage and control structures 
355 associated with a mutex.  In the current implementation, this function does nothing 
356 except when running with the statistics gathering implementation of mutexes, but 
357 this is not guaranteed to stay true in later releases of the OSI library.  Furthermore, 
358 anyone can enable statistics gathering.
359 \par
361 Locks and mutexes need not be finalized if the process is about to terminate, since any 
362 resources allocated are allocated on behalf of the process, and will be freed when 
363 the process exits.
365 \page
367 #{\footnote lockTryMutex}
368 ${\footnote lock_TryMutex}
369 K{\footnote lock_TryMutex}
370 +{\footnote mutexes:06}
372 \fs40
373 int \cf2 lock_TryMutex \cf0 (osi_mutex_t *mutexp)
374 \fs25
375 \par
377 This function is a non-blocking version of {\uldb lock_ObtainMutex}{\v lockObtainMutex}.  
378 It tries to obtain the specified mutex, and if it succeeds, it returns 1.  Otherwise, 
379 instead of blocking and waiting until the mutex is available, it returns 0 and leaves 
380 the mutex unchanged.
381 \par
383 This function is typically used when the programmer needs to obtain locks in an order 
384 incompatible with their locking hierarchy.  See the section on {\uldb locking hierarchies} 
385 {\v hierarchies} for an example of its use for this purpose.
386 \par
388 The caller must be careful to release the mutex if and only if the function returns 1.
389 \par
391 \page
393 #{\footnote rwlocks}
394 ${\footnote Read/Write Locks}
395 +{\footnote rwlocks:01}
397 Read/write locks are similar in use to mutexes.  They are used to mediate access to 
398 data structures that are accessed by multiple threads.
399 \par
401 Unlike {\uldb mutexes}{\v mutexes}, however, read/write locks mediate two forms of access 
402 to the structures: read accesses, of which several can be executing concurrently, and write 
403 accesses, only one of which can be executing at any given time.
404 \par
406 Like mutexes, read/write locks \cf1 must \cf0 be initialized before they can be used, and need 
407 to be finalized when their storage is going to be freed.  The procedures
408 {\uldb lock_InitializeRWLock}{\v lockInitializeRWLock} and 
409 {\uldb lock_FinalizeRWLock}{\v lockFinalizeRWLock} perform these functions.
411 \page
413 #{\footnote lockInitializeRWLock}
414 ${\footnote lock_InitializeRWLock}
415 K{\footnote lock_InitializeRWLock}
416 +{\footnote rwlocks:02}
418 \fs40
419 void \cf2 lock_InitializeRWLock \cf0 (osi_rwlock_t *lockp)
420 \fs25
421 \par
423 This function initializes the storage used by a read/write lock.  The structure 
424 \cf1 must \cf0 be initialized before it is obtained or released by the functions 
425 described in this section.
426 \par
428 \page
430 #{\footnote lockObtainRead}
431 ${\footnote lock_ObtainRead}
432 K{\footnote lock_ObtainRead}
433 +{\footnote rwlocks:03}
435 \fs40
436 void \cf2 lock_ObtainRead \cf0 (osi_rwlock_t *lockp)
437 \fs25
438 \par
440 This function obtains a read/write lock for reading.  The lock must have been
441 previously initialized with {\uldb lock_InitializeRWLock}{\v lockInitializeRWLock}.  
442 \par
444 When done with the lock, the programmer must ensure that the function 
445 {\uldb lock_ReleaseRead}{\v lockReleaseRead} or 
446 {\uldb osi_SleepR}{\v osiSleepR} is called to release the lock. 
448 \page
450 #{\footnote lockObtainWrite}
451 ${\footnote lock_ObtainWrite}
452 K{\footnote lock_ObtainWrite}
453 +{\footnote rwlocks:04}
455 \fs40
456 void \cf2 lock_ObtainWrite \cf0 (osi_rwlock_t *lockp)
457 \fs25
458 \par
460 This function obtains a read/write lock for writing.  The lock must have been 
461 previously initialized with {\uldb lock_InitializeRWLock}{\v lockInitializeRWLock}.
462 \par
464 At most one thread can have a read/write lock held for writing at any time, and 
465 no thread can simultaneously have a read/write lock held for reading at that time.
466 \par
468 When done with the lock, the programmer must ensure that the function 
469 {\uldb lock_ReleaseWrite}{\v lockReleaseWrite} or 
470 {\uldb osi_SleepW}{\v osiSleepW} is called to release the lock.
472 \page
474 #{\footnote lockReleaseRead}
475 ${\footnote lock_ReleaseRead}
476 K{\footnote lock_ReleaseRead}
477 +{\footnote rwlocks:05}
479 \fs40
480 void \cf2 lock_ReadRead\cf0 (osi_rwlock_t *lockp)
481 \fs25
482 \par
484 This function releases a lock held in read mode.  If the number of readers 
485 drops to zero, a writer may obtain the lock, otherwise only readers may 
486 obtain the lock.  If any writers are waiting for this lock, they are woken 
487 up and may proceed at this time.
488 \par
490 The application program must have obtained this lock in read mode before calling 
491 this function; it is an error to release a read lock more often than it was 
492 obtained.
493 \par
495 \page
497 #{\footnote lockReleaseWrite}
498 ${\footnote lock_ReleaseWrite}
499 K{\footnote lock_ReleaseWrite}
500 +{\footnote rwlocks:06}
502 \fs40
503 void \cf2 lock_ReleaseWrite\cf0 (osi_rwlock_t *lockp)
504 \fs25
505 \par
507 This function releases a lock held in write mode.  After this call, 
508 anyone waiting for a read lock or a write lock is woken up and may 
509 proceed.
510 \par
512 The application program must have obtained this lock in read mode before calling 
513 this function; it is an error to release a read lock more often than it was 
514 obtained.
515 \par
517 \page
519 #{\footnote lockFinalizeRWLock}
520 ${\footnote lock_FinalizeRWLock}
521 K{\footnote lock_FinalizeRWLock}
522 +{\footnote rwlocks:07}
524 \fs40
525 void \cf2 lock_FinalizeRWLock \cf0 (osi_rwlock_t *lockp)
526 \fs25
527 \par
529 This function is called to free up any auxiliary data structures associated with 
530 the read/write lock.  This function \cf1 must \cf0 be called before freeing any 
531 storage containing a read/write lock.  This function must be called at a time when 
532 there are no threads holding or waiting for the lock concerned.
533 \par
535 Locks allocated from static storage need never be finalized.
536 \par
538 \page
540 #{\footnote lockTryRead}
541 ${\footnote lock_TryRead}
542 K{\footnote lock_TryRead}
543 +{\footnote rwlocks:08}
545 \fs40
546 int \cf2 lock_TryRead\cf0 (osi_rwlock_t *rwlockp)
547 \fs25
548 \par
550 This function is a non-blocking version of {\uldb lock_ObtainRead}{\v
551 lockObtainRead}.   It tries to obtain the specified read/write lock in 
552 read mode, and if it succeeds, it returns 1.  Otherwise,  instead of 
553 blocking and waiting until the lock is available, it returns 0 and 
554 leaves the lock unchanged. 
555 \par
557 This function is typically used when the programmer needs to obtain locks in an order 
558 incompatible with their locking hierarchy.  See the section on {\uldb locking hierarchies} 
559 {\v hierarchies} for an example of its use for this purpose.
560 \par
562 The caller must be careful to release the read lock if and only if the function returns 1.
563 \par
565 \page
567 #{\footnote lockTryWrite}
568 ${\footnote lock_TryWrite}
569 K{\footnote lock_TryWrite}
570 +{\footnote rwlocks:09}
572 \fs40
573 int \cf2 lock_TryWrite\cf0 (osi_rwlock_t *rwlockp)
574 \fs25
575 \par
577 This function is a non-blocking version of {\uldb lock_ObtainWrite}{\v
578 lockObtainWrite}.   It tries to obtain the specified read/write lock in 
579 write mode, and if it succeeds, it returns 1.  Otherwise,  instead of 
580 blocking and waiting until the lock is available, it returns 0 and 
581 leaves the lock unchanged. 
582 \par
584 This function is typically used when the programmer needs to obtain locks in an order 
585 incompatible with their locking hierarchy.  See the section on {\uldb locking hierarchies} 
586 {\v hierarchies} for an example of its use for this purpose.
587 \par
589 The caller must be careful to release the write lock if and only if the function returns 1.
590 \par
592 \page
594 #{\footnote conds}
595 ${\footnote Condition Variables}
596 +{\footnote conds:01}
598 Condition variables are used to allow a threaded program to wait for an interesting 
599 event.
600 \par
602 Condition variables are represented as long integers.  By convention, these long 
603 integers are cast from addresses of mnemonic structures (so that, when waiting for a 
604 particular structure, foo, to change state, you might sleep on "(long)&foo"), but 
605 the sleep functions do not change any storage at the address named by the condition variable, 
606 and indeed, condition variable integers can really be any numbers you desire.
607 \par
609 The basic idea is that a thread that wants to wait for a particular event 
610 waits for a condition variable by calling \f1 osi_Sleep \f0 with the condition variable 
611 as a parameter, which blocks the calling thread.  When the interesting event occurs, 
612 the thread that notices the event calls \f1 osi_Wakeup \f0, waking up \cf1 all\cf0 
613 threads sleeping on that condition variable.
614 \par
616 Unfortunately, condition variables as described so far are unusable in most cases, due to 
617 a race condition that occurs in their typical uses.  Here's an example: assume that there 
618 is a structure that represents a buffer of data.  Some threads read from the buffer, waiting 
619 until there is data available, and others add data to the buffer, waiting until there is 
620 space available.  The structure, read and write calls might be coded like this:
622 \par
625 #define BSIZE   100     /* buffer size */\line
626 \line
627 typedef struct buffer \{\line
628     char data[BSIZE];   /* buffer */\line
629     int nbytes;         /* bytes used in the buffer */\line
630     osi_mutex_t mutex;  /* mutex for synchronizing access */\line
631     BOOL readWaiting;   /* true if someone is waiting for data */\line
632     BOOL writeWaiting;  /* true if someone is waiting for space */\line
633 \} buffer_t;\line
634 \par
636 int Read(buffer_t *bp, char *data)\line
637 \{\line
638     long bytesRead; \line
639     \line
640     while(1) \{ \line
641         lock_ObtainMutex(&bp->mutex);\line
642         if (nbytes == 0) \{ /* no data available */\line
643             readWaiting = 1;\line
644             /* wait for something interesting */\line
645             lock_ReleaseMutex(&bp->mutex);      /*BUG*/\line
646             osi_Sleep((long) &bp->readWaiting); /*BUG*/\line
647             continue; \line
648         \} \line
649         \line
650         memcpy(bp->data, data, bp->nbytes);\line
651         nbytes = bp->nbytes; /* remember for later */ \line
652         bp->nbytes = 0; \line
653         \line
654         /* now wakeup anyone waiting for space */ \line
655         if (bp->writeWaiting) \{ \line
656             bp->writeWaiting = 0; \line
657             osi_Wakeup((long) &bp->writeWaiting); \line
658         \} \line
659         \line
660         /* and we're done, so return # of bytes read */ \line
661         lock_ReleaseMutex(&bp->mutex);\line
662         return nbytes;\line
663     \}\line
664 \}\line
665 \par
667 void Write(buffer_t *bp, char *data, int len) \line
668 \{ \line
669     while(1) \{ \line
670         lock_ObtainMutex(&bp->mutex); \line
671         if (len > BSIZE-bp->nbytes) \{ \line
672             /* no space available */\line
673             writeWaiting = 1;\line
674             /* wait for something interesting */\line
675             lock_ReleaseMutex(&bp->mutex);       /*BUG*/ \line
676             osi_Sleep((long) &bp->writeWaiting); /*BUG*/ \line
677             continue; \line
678         \} \line
679         \line
680         memcpy(data, bp->data+bp->nbytes, len);\line
681         bp->nbytes += len; \line
682         \line
683         /* now wakeup anyone waiting for data */ \line
684         if (bp->readWaiting) \{ \line
685             bp->readWaiting = 0; \line
686             osi_Wakeup((long) &bp->readWaiting); \line
687         \} \line
688         \line
689         /* and we're done, so return # of bytes read */ \line
690         lock_ReleaseMutex(&bp->mutex);\line
691         return ;\line
692     \}\line
693 \} \line
694 \par
697 There are a number of things to note in the above example.  First, note our use of 
698 memory addresses as condition variables.  The calls to {\uldb osi_Sleep}{\v osiSleep} and 
699 {\uldb osi_Wakeup}{\v osiWakeup} do not change the data at bp->readWaiting or bp->writeWaiting, 
700 but the call \f1 osi_Wakeup((long) &bp->readWaiting)\f0 only wakes up the thread sleeping 
701 in the call \f1 osi_Sleep((long) &bp->readWaiting)\f0, not 
702 \f1 osi_Sleep((long) &bp->writeWaiting) \f0.
703 \par
705 Please also note that accesses by multiple threads to this buffer structure are mediated 
706 by a mutex structure stored in the buffer itself.  Whenever either \f1 Read\f0 or \f1 Write\f0 
707 block waiting for the other to supply/remove data, they of course must release the mutex 
708 so that the other thread can access the structure to supply/remove the data.
709 \par
711 Unfortunately, there is also a bug in the above code: consider the case 
712 where the \f1 Read\f0 call is interrupted due to a clock interrupt 
713 between the time that a thread releases the mutex and  the time that 
714 the thread then calls \f1 osi_Sleep\f0.  Assume that the OS does a context switch 
715 to a new thread, that calls \f1 Write\f0, and runs through completely, doing the call 
716 to \f1 osi_Wakeup\f0.  The OS then switches back to the thread doing the read, 
717 and the thread proceeds and calls \f1 osi_Sleep\f0, even though there is data now waiting.  
718 Unfortunately, no one is going to wake us up to notice that there is data available now.
719 \par
721 This problem would be solved if it were impossible for a wakeup call to execute between 
722 the time that the mutex was released and the time that the thread blocked in \f1 osi_Sleep\f0.  
723 This combination of releasing a lock or a mutex and sleeping on a condition variable is provided 
724 by three functions, {\uldb osi_SleepM}{\v osiSleepM}, {\uldb osi_SleepR}{\v osiSleepR} and 
725 {\uldb osi_SleepW}{\v osiSleepW}, which atomically sleep and release a mutex, read lock and 
726 write lock, respectively.
727 \par
729 Thus, the two pairs of lines in the example source above that are labelled with 
730 \f1 /*BUG*/\f0 should 
731 be replaced by \f1 osi_SleepM((long) &bp->readWaiting, &bp->mutex) \f0 and 
732 \f1 osi_SleepM((long) &bp->writeWaiting, &bp->mutex)\f0 , respectively.
734 Indeed, almost every use of \f1 osi_Sleep\f0 instead of one of the combination routines described 
735 above is incorrect, and has a race condition between the last release of a lock or mutex, and 
736 the call to \f1 osi_Sleep\f0.  So, please be careful when using \f1 osi_Sleep\f0 to be sure 
737 to check for this condition.
738 \par
740 \page
742 #{\footnote osiSleepM}
743 ${\footnote osi_SleepM}
744 K{\footnote osi_SleepM}
745 +{\footnote conds:02}
748 \fs40
749 void \cf2 osi_SleepM\cf0 (long sleepValue, osi_mutex_t *mutex)
750 \fs25
752 \par
754 This function atomically sleeps at \f1 sleepValue\f0 and releases the mutex at 
755 \f1 mutex\f0.  Atomically in this case means that no \f1 osi_Wakeup\f0 calls will 
756 be executed from 
757 before the lock is released until after the thread is asleep.
758 \par
760 The programmer must \cf1 always\cf0  be prepared for rare, spontaneous wakeups from 
761 any of the \f1 osi_Sleep\f0 family of functions.  Thus, any use of \f1 osi_SleepM\f0 
762 should be contained within a \f1 while \f0 loop that rechecks the appropriate condition 
763 that the thread is waiting for, and tries sleeping again if the wakeup was a spurious one.
764 \par
766 \page
768 #{\footnote osiSleepR}
769 ${\footnote osi_SleepR}
770 K{\footnote osi_SleepR}
771 +{\footnote conds:03}
774 \fs40
775 void \cf2 osi_SleepR\cf0 (long sleepValue, osi_rwlock_t *lockp)
776 \fs25
778 \par
780 This function atomically sleeps at \f1 sleepValue\f0 and releases the read lock at 
781 \f1 lockp\f0.  Atomically in this case means that no \f1 osi_Wakeup\f0 calls will 
782 be executed from 
783 before the lock is released until after the thread is asleep.
784 \par
786 The programmer must \cf1 always\cf0  be prepared for rare, spontaneous wakeups from 
787 any of the \f1 osi_Sleep\f0 family of functions.  Thus, any use of \f1 osi_SleepR\f0 
788 should be contained within a \f1 while \f0 loop that rechecks the appropriate condition 
789 that the thread is waiting for, and tries sleeping again if the wakeup was a spurious one.
790 \par
792 \page
794 #{\footnote osiSleepW}
795 ${\footnote osi_SleepW}
796 K{\footnote osi_SleepW}
797 +{\footnote conds:04}
800 \fs40
801 void \cf2 osi_SleepW\cf0 (long sleepValue, osi_rwlock_t *lockp)
802 \fs25
804 \par
806 This function atomically sleeps at \f1 sleepValue\f0 and releases the write lock at 
807 \f1 lockp\f0.  Atomically in this case means that no \f1 osi_Wakeup\f0 calls will 
808 be executed from 
809 before the lock is released until after the thread is asleep.
810 \par
812 The programmer must \cf1 always\cf0  be prepared for rare, spontaneous wakeups from 
813 any of the \f1 osi_Sleep\f0 family of functions.  Thus, any use of \f1 osi_SleepW\f0 
814 should be contained within a \f1 while \f0 loop that rechecks the appropriate condition 
815 that the thread is waiting for, and tries sleeping again if the wakeup was a spurious one.
816 \par
818 \page
820 #{\footnote osiSleep}
821 ${\footnote osi_Sleep}
822 K{\footnote osi_Sleep}
823 +{\footnote conds:05}
826 \fs40
827 void \cf2 osi_Sleep\cf0 (long sleepValue)
828 \fs25
830 \par
832 This function sleeps at \f1 sleepValue\f0.  The thread will not resume execution until 
833 after another thread later executes a call to \f1 osi_Wakeup\f0 with the same value 
834 for \f1 sleepValue\f0.
835 \par
837 The programmer must \cf1 always\cf0  be prepared for rare, spontaneous wakeups from 
838 any of the \f1 osi_Sleep\f0 family of functions.  Thus, any use of \f1 osi_Sleep\f0 
839 should be contained within a \f1 while \f0 loop that rechecks the appropriate condition 
840 that the thread is waiting for, and tries sleeping again if the wakeup was a spurious one.
841 \par
843 Also remember that almost every use of this function when waiting for a change in data protected 
844 by a mutex or read/write lock is incorrect, and you probably should be using one of 
845 {\uldb osi_SleepM}{\v osiSleepM}, 
846 {\uldb osi_SleepR}{\v osiSleepR}, 
847 or {\uldb osi_SleepW}{\v osiSleepW} to simultaneously release the data protection lock and 
848 sleep atomically.
850 \page
852 #{\footnote osiWakeup}
853 ${\footnote osi_Wakeup}
854 K{\footnote osi_Wakeup}
855 +{\footnote conds:06}
858 \fs40
859 void \cf2 osi_Wakeup\cf0 (long sleepValue)
861 \fs25
862 \par
864 This function wakes up all threads already sleeping at \f1 sleepValue\f0.  Threads sleep
865 by calling {\uldb osi_Sleep}{\v osiSleep}, 
866 {\uldb osi_SleepM}{\v osiSleepM}, 
867 {\uldb osi_SleepR}{\v osiSleepR}, 
868 or {\uldb osi_SleepW}{\v osiSleepW}.
869 \par
871 This call will synchronize appropriately with 
872 {\uldb osi_SleepM}{\v osiSleepM}, 
873 {\uldb osi_SleepR}{\v osiSleepR}, 
874 and {\uldb osi_SleepW}{\v osiSleepW}, so that if it is called while the corresponding lock 
875 or mutex is held, the \f1 osi_Wakeup\f0  function won't execute until after the thread sleeping 
876 on the condition variable is blocked.  This avoid race conditions of the form described in 
877 the section on {\uldb condition variables}{\v conds}.
878 \par
880 \page
882 #{\footnote hierarchies}
883 ${\footnote Locking Hierarchies}
884 +{\footnote hier:01}
886 Whenever a thread obtains more than one lock at a time, there is a 
887 possibility of deadlock if the locks are obtained in the wrong order.  
888 For example, imagine a situation where there are two threads, numbered 
889 1 and 2, and two locks, named A and B.  If thread 1 tries to obtain 
890 lock A first and then lock B, while thread 2 tries to lock B and then 
891 lock A, these two threads will, on occasion, deadlock.
892 \par
894 Specifically, what can happen is that thread 1 can obtain lock A, and 
895 then lose the processor to thread 2, which then goes on to obtain lock 
896 B.  Thread 2, after obtaining lock B, tries to obtain lock A, and 
897 blocks, since thread 1 already holds this lock.  Eventually, thread 1 
898 runs again, and tries to obtain lock B, but this lock is held (by 
899 thread 2), and so thread 1 blocks, still holding lock A.  This is a 
900 classical case of a deadlock, or deadly embrace.
901 \par
903 The heart of the problem is that two locks are obtained at the same
904 time, but in different orders by different threads.  And so, this
905 problem can be solved in several different ways, some of which will be
906 discussed here.
908 The easiest way to solve this problem is to have a global locking order, 
909 and have all threads lock their locks in this ordering.  It is of course 
910 imperative to come up with a reasonable locking hierarchy (ordering) to 
911 make this as easy as possible.  This solution is particularly good to 
912 use when dealing with several locks in the same module or package, since 
913 all of the locks can be understood by one programmer.  Among locks held 
914 by separate modules, as long as there is a standard ordering in which modules 
915 call one another, so that for example module foo always calls module bar, while 
916 module bar never calls module foo, the locking hierarchy within the individual 
917 modules will naturally extend to the set of all modules.
918 \par
920 Sometimes getting a simple locking hierarchy is difficult to do, 
921 however.  When establishing a good locking hierarchy is difficult or 
922 impossible, another possibility is releasing one lock when obtaining 
923 another lock.  In the example above, thread 1 might grab lock A, do some 
924 work, drop lock A and obtain lock B, do more work, and then drop lock B 
925 and grab lock A.  Since it never holds two locks at once, it avoids the 
926 deadlock.  However, when it grabs lock A for a second time, it must be 
927 prepared to see changes made to the structures protected by lock A, 
928 since for a time lock A was not held.  Furthermore, if lock A was a 
929 write lock or a mutex, we also must examine all other threads that might 
930 have seen the data structure protected by lock A in the state after we 
931 released the lock A the first time.  We must ensure that they view the 
932 state they might see as a consistent state, and are prepared to deal 
933 with the structures in that state. 
934 \par
936 Finally, another choice we have is to use the \f1 lock_TryRead\f0 and similar functions.  
937 Since the trylock functions don't block, we can use them safely to 
938 obtain the second through Nth locks in a series.  For example, the sequence:
939 \par
942     lock_ObtainWrite(&lockB); \line
943     lock_ObtainWrite(&lockA); \line
945 \par
947 can be replaced by this:
948 \par
951     while (1) \{ \line
952         lock_ObtainWrite(&lockB); \line
953         if (lock_TryWrite(&lockA)) break; \line
954         \line
955         /* otherwise we failed to get lock A, so camp on it \line
956          * safely. \line
957          */ \line
958         lock_ReleaseWrite(&lockB); \line
959         lock_ObtainWrite(&lockA); \line
960         \line
961         /* once we get here, we've gotten lock A.  Hopefully \line
962          * lock B is now available, too.  Let's quickly drop \line
963          * this guy and try again. \line
964          */ \line
965         lock_ReleaseWrite(&lockA); \line
966     \} \line
967     \line
968     /* when we get here, we have locked B and then A without having \line
969      * released B while obtaining A (in the last iteration). \line
970      */\line
972 \par
974 Clearly the second piece of code is considerably more complex, but it does give 
975 the programmer the ability to lock locks out of order, and do computations based on 
976 the information seen under those locks.  All modifications, of course, must be delayed 
977 until all of the locks have been obtained at the exit of the big while loop, but that is 
978 usually not a significant restriction.
979 \par
981 \page
983 #{\footnote debug}
984 ${\footnote Debugging and Profiling}
985 +{\footnote debug:01}
987 The state of any instance of the OSI package can be examined remotely by the 
988 osidebug program, if the programmer so chooses.  In order to export the basic information, 
989 which consists of information on the thread IDs and sleep values for threads blocked in 
990 one of the \f1 osi_Sleep\f0  functions, or blocked waiting for a lock.  The sleep value 
991 of a thread waiting for a lock is the address of the lock.
992 \par
994 Furthermore, if lock statistics gathering has been enabled by calling 
995 {\uldb osi_LockTypeSetDefault}{\v osiLockTypeSetDefault} before initializing some locks, 
996 then statistics are gathered on those locks, and the osidebug program will report those 
997 statistics, too.
998 \par
1000 To access any information remotely, the function 
1001 {\uldb osi_InitDebug}{\v osiInitDebug} must be called.  If this is not done, then 
1002 the osidebug program will simply fail to bind to the application program.
1003 \par
1005 If the system deadlocks, enough information may be available from osidebug's output to 
1006 enable the programmer to figure out what is wrong with the application program without 
1007 resorting to a debugger on the target machine; this is especially convenient when debugging 
1008 problems from a remote machine.
1009 \par
1011 More detailed information on osidebug can be obtained from that program's help menu.
1012 \par
1014 \page
1016 #{\footnote osilocktypesetdefault}
1017 ${\footnote osi_LockTypeSetDefault}
1018 K{\footnote osi_LockTypeSetDefault}
1019 +{\footnote debug:02}
1022 \fs40
1023 int \cf2 osi_LockTypeSetDefault\cf0 (char *name)
1024 \fs25
1026 \par
1028 This function takes a name of a lock type and sets a global state variable controlling 
1029 the type of lock initialized by \f1 lock_InitializeMutex\f0  and \f1 lock_InitializeRWLock\f0 .  
1030 Normally, when a lock initialization function is called, it creates a lock of a specific 
1031 type, currently, a regular lock or mutex, or a statistics-gathering lock or mutex.  Which 
1032 type is created is determined by this global variable.
1033 \par
1035 If the name is "stat", then statistics gathering locks and mutexes will be created.  If the 
1036 type name is passed in as a NULL pointer, regular, non-statistics gathering lock and mutexes 
1037 will be created.
1038 \par
1040 Since this is a global variable, it controls the type of lock and mutex created by all threads 
1041 henceforth in this process.
1042 \par
1044 Note that it does not matter what the state of default lock type is when you are gathering 
1045 statistics.  
1046 \cf1 All that matter is the type of default lock at the time the locks are initialized. \cf0
1047 \par
1049 The system initializes itself creating regular locks and mutexes; this function must be 
1050 used to enable statistics gathering, and it must be called \cf1 before\cf0  the 
1051 calls to \f1 lock_InitializeMutex\f0  and \f1 lock_InitializeRWLock\f0  are done that 
1052 initialize the locks whose statistics are to be gathered.  After the locks have been 
1053 initialized, this variable may even be reset, and the initialized locks will continue 
1054 to gather statistics.
1055 \par
1057 \page