Kernel/debug - Clean up Debug() method, bind to #define config
[tpg/acess2.git] / Tools / nativelib / rwlock.c
1 /*
2  * Acess2 libnative (Kernel Simulation Library)
3  * - By John Hodge (thePowersGang)
4  *
5  * rwlock.c
6  * - Read/Write locks
7  */
8 #include <acess.h>
9 #include <rwlock.h>
10 #include <events.h>
11 #include <threads_int.h>
12
13 // === CODE ===
14 int RWLock_AcquireRead(tRWLock *Lock)
15 {
16         SHORTLOCK(&Lock->Protector);
17         while( Lock->Level < 0 || Lock->WriterWaiting )
18         {
19                 // Wait
20                 tThread *me = Proc_GetCurThread();
21                 me->ListNext = NULL;
22                 if( Lock->ReaderWaiting )
23                         Lock->ReaderWaitingLast->Next = me;
24                 else
25                         Lock->ReaderWaiting = me;
26                 Lock->ReaderWaitingLast = me;
27                 SHORTREL(&Lock->Protector);
28                 Threads_WaitEvents(THREAD_EVENT_RWLOCK);
29                 SHORTLOCK(&Lock->Protector);
30         }
31         Lock->Level ++;
32         SHORTREL(&Lock->Protector);
33         return 0;
34 }
35
36 int RWLock_AcquireWrite(tRWLock *Lock)
37 {
38         SHORTLOCK(&Lock->Protector);
39
40         while( Lock->Level != 0 )
41         {
42                 tThread *me = Proc_GetCurThread();
43                 me->ListNext = NULL;
44                 if( Lock->WriterWaiting )
45                         Lock->WriterWaitingLast->Next = me;
46                 else
47                         Lock->WriterWaiting = me;
48
49                 SHORTREL(&Lock->Protector);
50                 Threads_WaitEvents(THREAD_EVENT_RWLOCK);
51                 SHORTLOCK(&Lock->Protector);
52         }
53         Lock->Level = -1;
54         SHORTREL(&Lock->Protector);
55         return 0;
56 }
57
58 void RWLock_Release(tRWLock *Lock)
59 {
60         SHORTLOCK(&Lock->Protector);
61         if( Lock->Level == -1 || Lock->Level == 1 )
62         {
63                 // Last reader or a writer yeilding
64                 // - Yields to writers first, then readers
65                 if( Lock->WriterWaiting )
66                 {
67                         Threads_PostEvent(Lock->WriterWaiting, THREAD_EVENT_RWLOCK);
68                         Lock->WriterWaiting = Lock->WriterWaiting->ListNext;
69                 }
70                 else
71                 {
72                         while(Lock->ReaderWaiting)
73                         {
74                                 Threads_PostEvent(Lock->ReaderWaiting, THREAD_EVENT_RWLOCK);
75                                 Lock->ReaderWaiting = Lock->ReaderWaiting->ListNext;
76                         }
77                 }
78                 // Nobody to wake, oh well
79                 Lock->Level = 0;
80         }
81         else if( Lock->Level == 0 )
82         {
83                 // ... oops?
84         }
85         else
86         {
87                 Lock->Level --;
88         }
89         SHORTREL(&Lock->Protector);
90 }
91

UCC git Repository :: git.ucc.asn.au