3 * - By John Hodge (thePowersGang)
6 * - Reader-Writer Lockes
10 #include <threads_int.h>
15 // Acquire as a reader (see rwlock.h for documentation)
17 int RWLock_AcquireRead(tRWLock *Lock)
20 LOG("Acquire RWLock Read %p", Lock);
22 SHORTLOCK( &Lock->Protector );
24 // Check if the lock is already held by a writer
28 SHORTLOCK( &glThreadListLock );
30 // - Remove from active list
31 us = Threads_RemActive();
34 us->Status = THREAD_STAT_RWLOCKSLEEP;
35 us->WaitPointer = Lock;
38 if(Lock->ReaderWaiting)
39 Lock->ReaderWaitingLast->Next = us;
41 Lock->ReaderWaiting = us;
42 Lock->ReaderWaitingLast = us;
45 Log("%p (%i %s) waiting on rwlock %p",
46 us, us->TID, us->ThreadName, Lock);
49 SHORTREL( &glThreadListLock );
50 SHORTREL( &Lock->Protector );
51 Threads_int_WaitForStatusEnd(THREAD_STAT_RWLOCKSLEEP);
52 // We're only woken when we get the lock
53 // TODO: Handle when this isn't the case
54 us->WaitPointer = NULL;
56 // Ooh, no problems then!
60 SHORTREL( & Lock->Protector );
67 int RWLock_AcquireWrite(tRWLock *Lock)
71 LOG("Acquire RWLock Write %p", Lock);
73 SHORTLOCK(&Lock->Protector);
74 if( Lock->Owner || Lock->Level != 0 )
77 SHORTLOCK(&glThreadListLock);
79 us = Threads_RemActive();
81 us->Status = THREAD_STAT_RWLOCKSLEEP;
82 us->WaitPointer = Lock;
84 if( Lock->WriterWaiting )
85 Lock->WriterWaitingLast->Next = us;
87 Lock->WriterWaiting = us;
88 Lock->WriterWaitingLast = us;
90 SHORTREL( &glThreadListLock );
91 SHORTREL( &Lock->Protector );
93 Threads_int_WaitForStatusEnd(THREAD_STAT_RWLOCKSLEEP);
94 us->WaitPointer = NULL;
98 // Nothing else is using the lock, nice :)
99 Lock->Owner = Proc_GetCurThread();
100 SHORTREL(&Lock->Protector);
107 void RWLock_Release(tRWLock *Lock)
109 LOG("Release RWLock %p", Lock);
110 SHORTLOCK( &Lock->Protector );
112 if( Lock->Owner != Proc_GetCurThread() )
116 if( Lock->WriterWaiting )
118 Lock->Owner = Lock->WriterWaiting; // Set owner
119 Lock->WriterWaiting = Lock->WriterWaiting->Next; // Next!
122 if( Lock->Owner->Status != THREAD_STAT_ACTIVE )
123 Threads_AddActive(Lock->Owner);
129 while( Lock->ReaderWaiting ) {
131 Threads_AddActive(Lock->ReaderWaiting);
132 Lock->ReaderWaiting = Lock->ReaderWaiting->Next;
135 SHORTREL( &Lock->Protector );
139 EXPORT(RWLock_AcquireRead);
140 EXPORT(RWLock_AcquireWrite);
141 EXPORT(RWLock_Release);