Kernel - Fixed double-lock caused by workqueue
[tpg/acess2.git] / Kernel / mutex.c
1 /*
2  * Acess2 Kernel
3  * - By John Hodge (thePowersGang)
4  *
5  * mutex.c
6  * - Mutexes
7  */
8 #include <acess.h>
9 #include <threads_int.h>
10 #include <mutex.h>
11
12 // === PROTOTYPES ===
13 #if 0
14  int    Mutex_Acquire(tMutex *Mutex);
15 void    Mutex_Release(tMutex *Mutex);
16  int    Mutex_IsLocked(tMutex *Mutex);
17 #endif
18
19 // === CODE ===
20 //
21 // Acquire mutex (see mutex.h for documentation)
22 //
23 int Mutex_Acquire(tMutex *Mutex)
24 {
25         tThread *us = Proc_GetCurThread();
26         
27         // Get protector
28         SHORTLOCK( &Mutex->Protector );
29         
30         //Log("Mutex_Acquire: (%p)", Mutex);
31         
32         // Check if the lock is already held
33         if( Mutex->Owner ) {
34                 SHORTLOCK( &glThreadListLock );
35                 // - Remove from active list
36                 us = Threads_RemActive();
37                 us->Next = NULL;
38                 // - Mark as sleeping
39                 us->Status = THREAD_STAT_MUTEXSLEEP;
40                 us->WaitPointer = Mutex;
41                 
42                 // - Add to waiting
43                 if(Mutex->LastWaiting) {
44                         Mutex->LastWaiting->Next = us;
45                         Mutex->LastWaiting = us;
46                 }
47                 else {
48                         Mutex->Waiting = us;
49                         Mutex->LastWaiting = us;
50                 }
51                 
52                 #if DEBUG_TRACE_STATE
53                 Log("%p (%i %s) waiting on mutex %p",
54                         us, us->TID, us->ThreadName, Mutex);
55                 #endif
56                 
57                 #if 0
58                 {
59                          int    i = 0;
60                         tThread *t;
61                         for( t = Mutex->Waiting; t; t = t->Next, i++ )
62                                 Log("[%i] (tMutex)%p->Waiting[%i] = %p (%i %s)", us->TID, Mutex, i,
63                                         t, t->TID, t->ThreadName);
64                 }
65                 #endif
66                 
67                 SHORTREL( &glThreadListLock );
68                 SHORTREL( &Mutex->Protector );
69                 while(us->Status == THREAD_STAT_MUTEXSLEEP)     Threads_Yield();
70                 // We're only woken when we get the lock
71                 us->WaitPointer = NULL;
72         }
73         // Ooh, let's take it!
74         else {
75                 Mutex->Owner = us;
76                 SHORTREL( &Mutex->Protector );
77         }
78         
79         #if 0
80         extern tMutex   glPhysAlloc;
81         if( Mutex != &glPhysAlloc )
82                 LogF("Mutex %p taken by %i %p\n", Mutex, us->TID, __builtin_return_address(0));
83         #endif
84         
85         return 0;
86 }
87
88 // Release a mutex
89 void Mutex_Release(tMutex *Mutex)
90 {
91         SHORTLOCK( &Mutex->Protector );
92         //Log("Mutex_Release: (%p)", Mutex);
93         if( Mutex->Waiting ) {
94                 Mutex->Owner = Mutex->Waiting;  // Set owner
95                 Mutex->Waiting = Mutex->Waiting->Next;  // Next!
96                 // Reset ->LastWaiting to NULL if we have just removed the last waiting thread
97                 // 2010-10-02 21:50 - Comemerating the death of the longest single
98                 //                    blocker in the Acess2 history. REMEMBER TO
99                 //                    FUCKING MAINTAIN YOUR FUCKING LISTS DIPWIT
100                 if( Mutex->LastWaiting == Mutex->Owner )
101                         Mutex->LastWaiting = NULL;
102                 
103                 // Wake new owner
104                 SHORTLOCK( &glThreadListLock );
105                 if( Mutex->Owner->Status != THREAD_STAT_ACTIVE )
106                         Threads_AddActive(Mutex->Owner);
107                 SHORTREL( &glThreadListLock );
108         }
109         else {
110                 Mutex->Owner = NULL;
111         }
112         SHORTREL( &Mutex->Protector );
113         
114         #if 0
115         extern tMutex   glPhysAlloc;
116         if( Mutex != &glPhysAlloc )
117                 LogF("Mutex %p released by %i %p\n", Mutex, Threads_GetTID(), __builtin_return_address(0));
118         #endif
119 }
120
121 // Check if a mutex is locked
122 int Mutex_IsLocked(tMutex *Mutex)
123 {
124         return Mutex->Owner != NULL;
125 }
126
127 // === EXPORTS ===
128 EXPORT(Mutex_Acquire);
129 EXPORT(Mutex_Release);
130 EXPORT(Mutex_IsLocked);

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