3 * - By John Hodge (thePowersGang)
6 * - Reader-Writer Lockes
9 #include <threads_int.h>
14 // Acquire as a reader (see rwlock.h for documentation)
16 int RWLock_AcquireRead(tRWLock *Lock)
20 SHORTLOCK( &Lock->Protector );
22 // Check if the lock is already held by a writer
25 SHORTLOCK( &glThreadListLock );
27 // - Remove from active list
28 us = Threads_RemActive();
31 us->Status = THREAD_STAT_RWLOCKSLEEP;
32 us->WaitPointer = Lock;
35 if(Lock->ReaderWaiting)
36 Lock->ReaderWaitingLast->Next = us;
38 Lock->ReaderWaiting = us;
39 Lock->ReaderWaitingLast = us;
42 Log("%p (%i %s) waiting on rwlock %p",
43 us, us->TID, us->ThreadName, Lock);
46 SHORTREL( &glThreadListLock );
47 SHORTREL( &Lock->Protector );
48 while(us->Status == THREAD_STAT_RWLOCKSLEEP) Threads_Yield();
49 // We're only woken when we get the lock
50 // TODO: Handle when this isn't the case
51 us->WaitPointer = NULL;
53 // Ooh, no problems then!
57 SHORTREL( & Lock->Protector );
63 int RWLock_AcquireWrite(tRWLock *Lock)
67 SHORTLOCK(&Lock->Protector);
68 if( Lock->Owner || Lock->Level != 0 )
70 SHORTLOCK(&glThreadListLock);
72 us = Threads_RemActive();
74 us->Status = THREAD_STAT_RWLOCKSLEEP;
75 us->WaitPointer = Lock;
77 if( Lock->WriterWaiting )
78 Lock->WriterWaitingLast->Next = us;
80 Lock->WriterWaiting = us;
81 Lock->WriterWaitingLast = us;
83 SHORTREL( &glThreadListLock );
84 SHORTREL( &Lock->Protector );
86 while(us->Status == THREAD_STAT_RWLOCKSLEEP) Threads_Yield();
87 us->WaitPointer = NULL;
91 // Nothing else is using the lock, nice :)
92 Lock->Owner = Proc_GetCurThread();
93 SHORTREL(&Lock->Protector);
99 void RWLock_Release(tRWLock *Lock)
101 SHORTLOCK( &Lock->Protector );
103 if( Lock->Owner == Proc_GetCurThread() )
107 if( Lock->WriterWaiting )
109 Lock->Owner = Lock->WriterWaiting; // Set owner
110 Lock->WriterWaiting = Lock->WriterWaiting->Next; // Next!
113 if( Lock->Owner->Status != THREAD_STAT_ACTIVE )
114 Threads_AddActive(Lock->Owner);
120 while( Lock->ReaderWaiting ) {
122 Threads_AddActive(Lock->ReaderWaiting);
123 Lock->ReaderWaiting = Lock->ReaderWaiting->Next;
126 SHORTREL( &Lock->Protector );
130 EXPORT(RWLock_AcquireRead);
131 EXPORT(RWLock_AcquireWrite);
132 EXPORT(RWLock_Release);