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

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