Tools/nativelib - Threading fixes
[tpg/acess2.git] / Tools / nativelib / threads.c
1 /*
2  * Acess2 libnative (Kernel Simulation Library)
3  * - By John Hodge (thePowersGang)
4  *
5  * threads.c
6  * - Threads handling
7  */
8 #include <acess.h>
9 #include <threads.h>
10 #include <threads_int.h>
11
12 // === PROTOTYPES ===
13 void    Threads_int_Init(void)  __attribute__((constructor(101)));
14 tThread *Threads_int_CreateTCB(tThread *Parent);
15
16 // === GLOBALS ===
17 tThread *gThreads_List;
18 tThread __thread        *lpThreads_This;
19  int    giThreads_NextTID = 1;
20 tShortSpinlock  glThreadListLock;
21
22 // === CODE ===
23 void Threads_int_Init(void)
24 {
25         lpThreads_This = Threads_int_CreateTCB(NULL);
26         Threads_SetName("ThreadZero");
27 }
28
29 tThread *Proc_GetCurThread(void)
30 {
31         return lpThreads_This;
32 }
33
34 void Threads_PostEvent(tThread *Thread, Uint32 Events)
35 {
36         if( !Thread ) {
37                 // nope.avi
38                 return ;
39         }
40         SHORTLOCK( &Thread->IsLocked );
41         Thread->PendingEvents |= Events;
42         if( Thread->WaitingEvents & Events )
43                 Threads_int_SemSignal(Thread->WaitSemaphore);
44         SHORTREL( &Thread->IsLocked );
45 }
46
47 Uint32 Threads_WaitEvents(Uint32 Events)
48 {
49         if( !Threads_int_ThreadingEnabled() ) {
50                 Log_Notice("Threads", "_WaitEvents: Threading disabled");
51                 return 0;
52         }
53         lpThreads_This->WaitingEvents = Events;
54         Threads_int_SemWaitAll(lpThreads_This->WaitSemaphore);
55         lpThreads_This->WaitingEvents = 0;
56         Uint32  rv = lpThreads_This->PendingEvents;
57         return rv;
58 }
59
60 void Threads_ClearEvent(Uint32 Mask)
61 {
62         if( !Threads_int_ThreadingEnabled() ) {
63                 Log_Notice("Threads", "_ClearEvent: Threading disabled");
64                 return ;
65         }
66         SHORTLOCK(&lpThreads_This->IsLocked);
67         lpThreads_This->PendingEvents &= ~Mask;
68         SHORTREL(&lpThreads_This->IsLocked);
69 }
70
71 tUID Threads_GetUID(void) { return 0; }
72 tGID Threads_GetGID(void) { return 0; }
73
74 tTID Threads_GetTID(void) { return lpThreads_This ? lpThreads_This->TID : 0; }
75
76 int *Threads_GetMaxFD(void)        { return &lpThreads_This->Process->MaxFDs;  }
77 char **Threads_GetCWD(void)        { return &lpThreads_This->Process->CWD;     }
78 char **Threads_GetChroot(void)     { return &lpThreads_This->Process->Chroot;  }
79 void **Threads_GetHandlesPtr(void) { return &lpThreads_This->Process->Handles; }
80
81 void Threads_Yield(void)
82 {
83         Log_KernelPanic("Threads", "Threads_Yield DEFINITELY shouldn't be used (%p)",
84                 __builtin_return_address(0));
85 }
86
87 void Threads_Sleep(void)
88 {
89         Log_Warning("Threads", "Threads_Sleep shouldn't be used");
90 }
91
92 void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
93 {
94         while( lpThreads_This->Status != Status )
95                 Threads_int_SemWaitAll(lpThreads_This->WaitSemaphore);
96 }
97
98 int Threads_SetName(const char *Name)
99 {
100         if( !lpThreads_This )
101                 return 0;
102
103         if( lpThreads_This->ThreadName )
104                 free(lpThreads_This->ThreadName);
105         lpThreads_This->ThreadName = strdup(Name);
106
107         return 0;
108 }
109
110 int *Threads_GetErrno(void) __attribute__ ((weak));
111
112 int *Threads_GetErrno(void)
113 {
114         static int a_errno;
115         return &a_errno;
116 }
117
118 tThread *Threads_RemActive(void)
119 {
120         return lpThreads_This;
121 }
122
123 void Threads_AddActive(tThread *Thread)
124 {
125         Thread->Status = THREAD_STAT_ACTIVE;
126         // Increment state-change semaphore
127         Threads_int_SemSignal(Thread->WaitSemaphore);
128 }
129
130 struct sProcess *Threads_int_CreateProcess(void)
131 {
132         struct sProcess *ret = calloc(sizeof(struct sProcess), 1);
133
134         ret->MaxFDs = 32;
135
136         return ret;
137 }
138
139 tThread *Threads_int_CreateTCB(tThread *Parent)
140 {
141         tThread *ret = calloc( sizeof(tThread), 1 );
142         ret->TID = giThreads_NextTID ++;
143         ret->WaitSemaphore = Threads_int_SemCreate();
144         //ret->Protector = Threads_int_MutexCreate();
145
146         if( !Parent )
147         {
148                 ret->Process = Threads_int_CreateProcess();
149         }
150         else
151                 ret->Process = Parent->Process;
152
153         ret->ProcNext = ret->Process->Threads;
154         ret->Process->Threads = ret;
155
156         ret->Next = gThreads_List;
157         gThreads_List = ret;
158         
159         return ret;
160 }
161
162 struct sThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
163 {
164         if( !Threads_int_ThreadingEnabled() )
165         {
166                 Log_Error("Threads", "Multithreading is disabled in this build");
167                 return NULL;
168         }
169         else
170         {
171                 tThread *ret = Threads_int_CreateTCB(lpThreads_This);
172                 ret->SpawnFcn = Fcn;
173                 ret->SpawnData = Data;
174                 Threads_int_CreateThread(ret);
175                 return ret;
176         }
177 }
178

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