Merge branch 'master' of git://git.ucc.asn.au/tpg/acess2
[tpg/acess2.git] / Tools / nativelib / threads_int.c
1 /*
2  * Acess2 libnative (Kernel Simulation Library)
3  * - By John Hodge (thePowersGang)
4  *
5  * threads_int.c
6  * - Internal threading functions
7  */
8 #include <stddef.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <acess_logging.h>
12 #include <threads_int.h>
13 #include <pthread_weak.h>
14 #include <shortlock.h>
15
16 // === TYPES ===
17 struct sThreadIntMutex { int lock; };
18 struct sThreadIntSem { int val; };
19
20 // === PROTOTYPES ===
21
22 // === CODE ===
23 int Threads_int_ThreadingEnabled(void)
24 {
25         return !!pthread_create;
26 }
27
28 tThreadIntMutex *Threads_int_MutexCreate(void)
29 {
30         if( pthread_mutex_init )
31         {
32                 tThreadIntMutex *ret = malloc(sizeof(pthread_mutex_t));
33                 pthread_mutex_init( (void*)ret, NULL );
34                 return ret;
35         }
36         else
37         {
38                 return calloc(sizeof(tThreadIntMutex), 1);
39         }
40 }
41
42 void Threads_int_MutexLock(tThreadIntMutex *Mutex)
43 {
44         if( !Mutex ) {
45                 return ;
46         }
47         if( pthread_mutex_lock )
48         {
49                 pthread_mutex_lock( (void*)Mutex );
50         }
51         else
52         {
53                 if( Mutex->lock )
54                         Log_KernelPanic("Threads", "Double mutex lock");
55                 Mutex->lock = 1;
56         }
57 }
58
59 void Threads_int_MutexRelease(tThreadIntMutex *Mutex)
60 {
61         if( !Mutex ) {
62                 return ;
63         }
64
65         if( pthread_mutex_unlock )
66         {
67                 pthread_mutex_unlock( (void*)Mutex );
68         }
69         else
70         {
71                 if( !Mutex->lock )
72                         Log_Notice("Threads", "Release of non-locked mutex %p", Mutex);
73                 Mutex->lock = 0;
74         }
75 }
76
77 tThreadIntSem *Threads_int_SemCreate(void)
78 {
79         if( sem_init )
80         {
81                 tThreadIntSem *ret = malloc(sizeof(sem_t));
82                 sem_init( (void*)ret, 0, 0 );
83                 return ret;
84         }
85         else
86         {
87                 return calloc(sizeof(tThreadIntSem), 1);
88         }
89 }
90
91 void Threads_int_SemSignal(tThreadIntSem *Sem)
92 {
93         if( sem_wait )
94         {
95                 sem_wait( (void*)Sem );
96         }
97         else
98         {
99                 Sem->val ++;
100         }
101 }
102
103 void Threads_int_SemWaitAll(tThreadIntSem *Sem)
104 {
105         if( sem_post )
106         {
107                 sem_post( (void*)Sem );
108         }
109         else
110         {
111                 if( !Sem->val )
112                         Log_KernelPanic("Threads", "Waiting on empty semaphre %p", Sem);
113                 Sem->val = 0;
114         }
115 }
116
117 void *Threads_int_ThreadRoot(void *ThreadPtr)
118 {
119         tThread *thread = ThreadPtr;
120         lpThreads_This = thread;
121         Log_Debug("Threads", "SpawnFcn: %p, SpawnData: %p", thread->SpawnFcn, thread->SpawnData);
122         thread->SpawnFcn(thread->SpawnData);
123         return NULL;
124 }
125
126 int Threads_int_CreateThread(tThread *Thread)
127 {
128         if( pthread_create )
129         {
130                 pthread_t *pthread = malloc(sizeof(pthread_t));
131                 Thread->ThreadHandle = pthread;
132                 return pthread_create(pthread, NULL, &Threads_int_ThreadRoot, Thread);
133         }
134         else
135         {
136                 Log_KernelPanic("Threads", "Link with pthreads to use threading");
137                 return -1;
138         }
139 }
140
141 void SHORTLOCK(tShortSpinlock *Lock)
142 {
143         if( !pthread_mutex_init )
144         {
145                 if(*Lock)       Log_KernelPanic("---", "Double short lock");
146                 *Lock = (void*)1;
147         }
148         else
149         {
150                 if( !*Lock ) {
151                         *Lock = malloc(sizeof(pthread_mutex_t));
152                         pthread_mutex_init(*Lock, NULL);
153                 }
154                 pthread_mutex_lock(*Lock);
155         }
156 }
157
158 void SHORTREL(tShortSpinlock *Lock)
159 {
160         if( !pthread_mutex_init )
161         {
162                 if(!*Lock)      Log_Notice("---", "Short release when not held");
163                 *Lock = NULL;
164         }
165         else
166         {
167                 pthread_mutex_unlock(*Lock);
168         }
169 }
170
171 int CPU_HAS_LOCK(tShortSpinlock *Lock)
172 {
173         return 0;
174 }
175

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