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

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