Tools/nativelib - More things implimented
[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
21 // === CODE ===
22 void Threads_int_Init(void)
23 {
24         lpThreads_This = Threads_int_CreateTCB(NULL);
25 }
26
27 tThread *Proc_GetCurThread(void)
28 {
29         return lpThreads_This;
30 }
31
32 void Threads_PostEvent(tThread *Thread, Uint32 Events)
33 {
34         if( !Thread ) {
35                 // nope.avi
36                 return ;
37         }
38         Threads_int_MutexLock(Thread->Protector);
39         Thread->PendingEvents |= Events;
40         if( Thread->WaitingEvents & Events )
41                 Threads_int_SemSignal(Thread->WaitSemaphore);
42         Threads_int_MutexRelease(Thread->Protector);
43 }
44
45 Uint32 Threads_WaitEvents(Uint32 Events)
46 {
47         if( !Threads_int_ThreadingEnabled() ) {
48                 Log_Notice("Threads", "_WaitEvents: Threading disabled");
49                 return 0;
50         }
51         lpThreads_This->WaitingEvents = Events;
52         Threads_int_SemWaitAll(lpThreads_This->WaitSemaphore);
53         lpThreads_This->WaitingEvents = 0;
54         Uint32  rv = lpThreads_This->PendingEvents;
55         return rv;
56 }
57
58 void Threads_ClearEvent(Uint32 Mask)
59 {
60         if( !Threads_int_ThreadingEnabled() ) {
61                 Log_Notice("Threads", "_ClearEvent: Threading disabled");
62                 return ;
63         }
64         Threads_int_MutexLock(lpThreads_This->Protector);
65         lpThreads_This->PendingEvents &= ~Mask;
66         Threads_int_MutexRelease(lpThreads_This->Protector);
67 }
68
69 tUID Threads_GetUID(void) { return 0; }
70 tGID Threads_GetGID(void) { return 0; }
71
72 tTID Threads_GetTID(void) { return lpThreads_This->TID; }
73
74 int *Threads_GetMaxFD(void)        { return &lpThreads_This->Process->MaxFDs;  }
75 char **Threads_GetCWD(void)        { return &lpThreads_This->Process->CWD;     }
76 char **Threads_GetChroot(void)     { return &lpThreads_This->Process->Chroot;  }
77 void **Threads_GetHandlesPtr(void) { return &lpThreads_This->Process->Handles; }
78
79 void Threads_Yield(void)
80 {
81         Log_KernelPanic("Threads", "Threads_Yield DEFINITELY shouldn't be used (%p)",
82                 __builtin_return_address(0));
83 }
84
85 void Threads_Sleep(void)
86 {
87         Log_Warning("Threads", "Threads_Sleep shouldn't be used");
88 }
89
90 int Threads_SetName(const char *Name)
91 {
92         if( !lpThreads_This )
93                 return 0;
94
95         if( lpThreads_This->Name )
96                 free(lpThreads_This->Name);
97         lpThreads_This->Name = strdup(Name);
98
99         return 0;
100 }
101
102 int *Threads_GetErrno(void) __attribute__ ((weak));
103
104 int *Threads_GetErrno(void)
105 {
106         static int a_errno;
107         return &a_errno;
108 }
109
110 struct sProcess *Threads_int_CreateProcess(void)
111 {
112         struct sProcess *ret = calloc(sizeof(struct sProcess), 1);
113
114         ret->MaxFDs = 32;
115
116         return ret;
117 }
118
119 tThread *Threads_int_CreateTCB(tThread *Parent)
120 {
121         tThread *ret = calloc( sizeof(tThread), 1 );
122         ret->TID = giThreads_NextTID ++;
123         ret->WaitSemaphore = Threads_int_SemCreate();
124         ret->Protector = Threads_int_MutexCreate();
125
126         if( !Parent )
127         {
128                 ret->Process = Threads_int_CreateProcess();
129         }
130         else
131                 ret->Process = Parent->Process;
132
133         ret->ProcNext = ret->Process->Threads;
134         ret->Process->Threads = ret;
135
136         ret->Next = gThreads_List;
137         gThreads_List = ret;
138         
139         return ret;
140 }
141
142 struct sThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
143 {
144         if( !Threads_int_ThreadingEnabled() )
145         {
146                 Log_Error("Threads", "Multithreading is disabled in this build");
147                 return NULL;
148         }
149         else
150         {
151                 tThread *ret = Threads_int_CreateTCB(lpThreads_This);
152                 ret->SpawnFcn = Fcn;
153                 ret->SpawnData = Data;
154                 Threads_int_CreateThread(ret);
155                 return ret;
156         }
157 }
158

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