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

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