root/Whitix/trunk/kernel/thread.c

Revision 1791, 8.4 KB (checked in by mwhitworth, 3 years ago)

Various formatting fixes.

Line 
1#include <sched.h>
2#include <module.h>
3#include <slab.h>
4#include <task.h>
5#include <print.h>
6#include <panic.h>
7#include <i386/process.h>
8#include <sys.h>
9#include <preempt.h>
10#include <malloc.h>
11
12/* Used when a thread is exiting */
13BYTE exitStack[PAGE_SIZE/4];
14
15Spinlock thrListLock;
16struct Cache* threadCache;
17extern int nrRunning;
18LIST_HEAD(threadList);
19
20/***********************************************************************
21 *
22 * FUNCTION: ThrCreateThread
23 *
24 * DESCRIPTION: Create a kernel/user thread.
25 *
26 * PARAMETERS: parent - the thread's parent.
27 *                         entry - the starting address of the thread.
28 *                         user - 1 for user, 0 for kernel.
29 *                         stackP - stack pointer of the new thread. Passed to
30 *                                              ThrArchCreateThread.
31 *
32 * RETURNS: pointer to thread information.
33 *
34 ***********************************************************************/
35
36struct Thread* ThrCreateThread(struct Process* parent,DWORD entry,int user,DWORD stackP, void* argument)
37{
38        struct Thread* ret;
39
40        ret=(struct Thread*)MemCacheAlloc(threadCache);
41        if (!ret)
42                return NULL;
43
44        ret->parent = parent;
45        ret->refs = 1;
46        ret->priority = PRIORITY_DEFAULT;
47        ret->state = THR_PAUSED;
48        ret->preemptCount = 0;
49
50        if (parent)
51                ret->id=parent->cId++;
52
53        ThrArchCreateThread(ret, entry, user, stackP, argument);
54
55        SpinLockIrq(&thrListLock);
56        ListAddTail(&ret->list, &threadList);
57        SpinUnlockIrq(&thrListLock);
58
59        return ret;
60}
61
62SYMBOL_EXPORT(ThrCreateThread);
63
64/***********************************************************************
65 *
66 * FUNCTION: ThrSetPriority
67 *
68 * DESCRIPTION: Sets a thread to a given priority for scheduling.
69 *
70 * PARAMETERS: thread - the thread in question.
71 *                         priority - the thread's new priority.
72 *
73 * RETURNS: Nothing.
74 *
75 ***********************************************************************/
76
77void ThrSetPriority(struct Thread* thread,int priority)
78{
79        if (priority > PRIORITY_TOP)
80                priority=PRIORITY_TOP;
81        else if (priority < PRIORITY_NONE)
82                priority=PRIORITY_NONE;
83
84        thread->priority=priority;
85}
86
87SYMBOL_EXPORT(ThrSetPriority);
88
89/***********************************************************************
90 *
91 * FUNCTION: _ThrFreeThread
92 *
93 * DESCRIPTION: Free the current thread and it's stack - stack must be
94 *                              switched via ArchSwitchStackCall to call this.
95 *
96 * PARAMETERS: thread - the current thread.
97 *
98 * RETURNS: Nothing.
99 *
100 ***********************************************************************/
101
102void _ThrFreeThread(struct Thread* thread)
103{
104        MemFree((void*)thread->currStack);
105        currThread=NULL;
106        MemCacheFree(threadCache, thread);
107        ThrSchedule();
108}
109
110/***********************************************************************
111 *
112 * FUNCTION: ThrFreeThread
113 *
114 * DESCRIPTION: Free all resources associated with a thread. Freeing the
115 *                              current thread is ok at the start of ThrSchedule.
116 *
117 * PARAMETERS: thread - the thread in question.
118 *
119 * RETURNS: Nothing.
120 *
121 ***********************************************************************/
122
123void ThrFreeThread(struct Thread* thread)
124{
125        DWORD flags;
126
127        if (thread == idleTask)
128                KernelPanic("Trying to free idle thread");
129
130        IrqSaveFlags(flags);
131
132        /*
133         * Free the thread's kernel stack, because that won't be run anymore.
134         * The exception is for the current thread, but that gets freed in
135         * _ThrFreeThread, where it doesn't run anymore.
136         */
137
138        ListRemove(&thread->list);
139        --nrRunning;
140
141        thread->currStack &= ~(ARCH_STACK_SIZE-1);
142       
143        /* FIXME: Free the user stack. */
144
145        if (thread == currThread)
146                ArchSwitchStackCall(exitStack+PAGE_SIZE/4, _ThrFreeThread, thread);
147        else{
148                MemFree((void*)(thread->currStack));
149                MemCacheFree(threadCache,thread);
150        }
151       
152        /* When thread is the current thread, doesn't get here as _ThrFreeThread reschedules */
153}
154
155SYMBOL_EXPORT(ThrFreeThread);
156
157/***********************************************************************
158 *
159 * FUNCTION: _ThrStartThread
160 *
161 * DESCRIPTION: Gets a thread running again - adding it to be scheduled
162 *                        etc.
163 *
164 * PARAMETERS: thread - the thread in question.
165 *
166 * RETURNS: Nothing.
167 *
168 ***********************************************************************/
169
170static void _ThrStartThread(struct Thread* thread)
171{
172        thread->state=THR_RUNNING;
173        ++nrRunning;
174}
175
176/***********************************************************************
177 *
178 * FUNCTION: ThrStartThread
179 *
180 * DESCRIPTION: Serializes access to _ThrStartThread
181 *
182 * PARAMETERS: thread - the thread in question.
183 *
184 * RETURNS: Nothing.
185 *
186 ***********************************************************************/
187
188void ThrStartThread(struct Thread* thread)
189{
190        if (LIKELY(thread->state != THR_RUNNING))
191        {
192                SpinLockIrq(&thrListLock);
193                _ThrStartThread(thread);
194                SpinUnlockIrq(&thrListLock);
195        }
196}
197
198SYMBOL_EXPORT(ThrStartThread);
199
200/***********************************************************************
201 *
202 * FUNCTION: ThrDoExitThread
203 *
204 * DESCRIPTION: Exit the current thread in the current process.
205 *
206 * PARAMETERS: None.
207 *
208 * RETURNS: Usual error codes.
209 *
210 ***********************************************************************/
211
212int ThrDoExitThread()
213{
214        currThread->state=THR_DYING;
215       
216        ThrReleaseThread(currThread); /* A waitqueue might still have a reference to this thread, so might not be freed */
217        ThrArchDestroyThread(currThread);
218        ThrSchedule();
219
220        return 0;
221}
222
223SYMBOL_EXPORT(ThrDoExitThread);
224
225/***********************************************************************
226 *
227 * FUNCTION:    ThrSuspendThread
228 *
229 * DESCRIPTION: Suspend a thread, by changing its state and reducing the
230 *                              number of threads running.
231 *
232 * PARAMETERS:  thread - the thread in question.
233 *
234 * RETURNS:             Nothing.
235 *
236 ***********************************************************************/
237
238void ThrSuspendThread(struct Thread* thread)
239{
240        if (thread == idleTask)
241                KernelPanic("Idle task being suspended - driver sleeping in interrupt?");
242
243        if (LIKELY(thread->state == THR_RUNNING))
244        {
245                SpinLockIrq(&thrListLock);
246                --nrRunning;
247               
248                thread->state=THR_PAUSED;
249                SpinUnlockIrq(&thrListLock);
250        }
251}
252
253SYMBOL_EXPORT(ThrSuspendThread);
254
255/***********************************************************************
256 *
257 * FUNCTION:    ThrResumeThread
258 *
259 * DESCRIPTION: Resume a paused thread, and signal scheduling if it's of
260 *                              a higher priority.
261 *
262 * PARAMETERS:  thread - the thread in question.
263 *
264 * RETURNS:             Nothing.
265 *
266 ***********************************************************************/
267
268void ThrResumeThread(struct Thread* thread)
269{
270        if (LIKELY(thread->state != THR_RUNNING))
271        {
272                ThrStartThread(thread);
273                       
274                if (thread->quantums >= currThread->quantums)
275                        thrNeedSchedule=true;
276        }
277}
278
279SYMBOL_EXPORT(ThrResumeThread);
280
281/***********************************************************************
282 *
283 * FUNCTION:    SysCreateThread
284 *
285 * DESCRIPTION: Creates a new thread in the current process with the
286 *                              instruction pointer set to 'address'.
287 *
288 * PARAMETERS:  address - the starting address of the thread.
289 *
290 * RETURNS:             Usual error codes.
291 *
292 ***********************************************************************/
293
294int SysCreateThread(DWORD address,DWORD stackP, void* argument)
295{
296        struct Thread* thread=ThrCreateThread(current, address, true, stackP, argument);
297
298        if (!thread)
299                return -ENOMEM;
300
301        ThrStartThread(thread);
302
303        if (thread->quantums > currThread->quantums)
304                ThrSchedule();
305
306        return thread->id;
307}
308
309int SysGetCurrentThreadId()
310{
311        return currThread->id;
312}
313
314struct Thread* ThrGetThreadById(struct Process* process, DWORD threadId)
315{
316        struct Thread* curr;
317
318        ListForEachEntry(curr, &threadList, list)
319        {
320                if (!curr->parent)
321                        continue;
322
323                if (curr->id == threadId && curr->parent == process)
324                        return curr;
325        }
326
327        return NULL;
328}
329
330int SysSuspendThread(DWORD threadId)
331{
332        struct Thread* thread;
333
334        thread=ThrGetThreadById(current, threadId);
335
336        if (!thread)
337                return -EINVAL;
338
339        ThrGetThread(thread);
340        ThrSuspendThread(thread);
341        ThrSchedule();
342
343        ThrReleaseThread(thread);
344
345        return 0;
346}
347
348int SysResumeThread(DWORD threadId)
349{
350        struct Thread* thread;
351
352        thread=ThrGetThreadById(current, threadId);
353
354        if (!thread)
355                return -EINVAL;
356
357        ThrResumeThread(thread);
358
359        return 0;
360}
361
362int SysExitThread(int threadId)
363{
364        if (threadId == -1) /* Exit current thread. */
365                ThrDoExitThread();
366        else
367                return -ENOTIMPL;
368
369        return 0;
370}
371
372struct SysCall thrSysCallTable[]=
373{
374        SysEntry(SysCreateThread, 12),
375        SysEntry(SysGetCurrentThreadId, 0),
376        SysEntry(SysSuspendThread, 4),
377        SysEntry(SysResumeThread, 4),
378        SysEntry(SysExitThread, 4),
379        SysEntryEnd()
380};
381
382int ThreadInit()
383{
384        threadCache=MemCacheCreate("Threads", sizeof(struct Thread), NULL, NULL, 0);
385        SysRegisterRange(SYS_THREAD_BASE, thrSysCallTable);
386        return 0;       
387}
Note: See TracBrowser for help on using the browser.