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

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