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

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