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

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