Loading [MathJax]/extensions/tex2jax.js
CS350 COS
COS
All Data Structures Files Functions Variables Typedefs Macros
thread.c File Reference
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/kassert.h>
#include <sys/kconfig.h>
#include <sys/kdebug.h>
#include <sys/kmem.h>
#include <sys/ktime.h>
#include <sys/mp.h>
#include <sys/spinlock.h>
#include <sys/thread.h>
#include <machine/trap.h>
#include <machine/pmap.h>
Include dependency graph for thread.c:

Go to the source code of this file.

Functions

void Handle_GlobalInit ()
 
void Thread_Init ()
 
void Thread_InitAP ()
 
ThreadThread_Create (Process *proc)
 
ThreadThread_KThreadCreate (void(*f)(void *), void *arg)
 
ThreadThread_UThreadCreate (Thread *oldThr, uint64_t rip, uint64_t arg)
 
static void Thread_Destroy (Thread *thr)
 
ThreadThread_Lookup (Process *proc, uint64_t tid)
 
void Thread_Retain (Thread *thr)
 
void Thread_Release (Thread *thr)
 
uint64_t Thread_Wait (Thread *thr, uint64_t tid)
 
void ThreadKThreadEntry (TrapFrame *tf) __NO_LOCK_ANALYSIS
 
void Thread_Dump (Thread *thr)
 
static void Debug_Threads (int argc, const char *argv[])
 
 REGISTER_DBGCMD (threads, "Display list of threads", Debug_Threads)
 
static void Debug_ThreadInfo (int argc, const char *argv[])
 
 REGISTER_DBGCMD (threadinfo, "Display current thread state", Debug_ThreadInfo)
 

Variables

Spinlock schedLock
 
ThreadQueue waitQueue
 
ThreadQueue runnableQueue
 
ThreadcurProc [MAX_CPUS]
 
Spinlock procLock
 
uint64_t nextProcessID
 
ProcessQueue processList
 
Slab processSlab
 
ProcesskernelProcess
 
Slab threadSlab
 
TaskStateSegment64 TSS [MAX_CPUS]
 

Function Documentation

◆ Debug_ThreadInfo()

static void Debug_ThreadInfo ( int  argc,
const char *  argv[] 
)
static

Definition at line 384 of file thread.c.

385{
386 Thread *thr = curProc[CPU()];
387
388 kprintf("Current Thread State:\n");
389 Thread_Dump(thr);
390}
#define CPU
Definition: mp.h:7
int kprintf(const char *fmt,...)
Definition: printf.c:210
Thread * curProc[MAX_CPUS]
Definition: sched.c:41
void Thread_Dump(Thread *thr)
Definition: thread.c:328
Definition: thread.h:31
Here is the call graph for this function:

◆ Debug_Threads()

static void Debug_Threads ( int  argc,
const char *  argv[] 
)
static

Definition at line 354 of file thread.c.

355{
356 Thread *thr;
357
358 //Spinlock_Lock(&threadLock);
359
360 for (int i = 0; i < MAX_CPUS; i++) {
361 thr = curProc[i];
362 if (thr) {
363 kprintf("Running Thread CPU %d: %d(%016llx) %d\n", i, thr->tid, thr, thr->ctxSwitches);
364 Thread_Dump(thr);
365 }
366 }
367 TAILQ_FOREACH(thr, &runnableQueue, schedQueue)
368 {
369 kprintf("Runnable Thread: %d(%016llx) %d\n", thr->tid, thr, thr->ctxSwitches);
370 Thread_Dump(thr);
371 }
372 TAILQ_FOREACH(thr, &waitQueue, schedQueue)
373 {
374 kprintf("Waiting Thread: %d(%016llx) %d\n", thr->tid, thr, thr->ctxSwitches);
375 Thread_Dump(thr);
376 }
377
378 //Spinlock_Unlock(&threadLock);
379}
#define MAX_CPUS
Definition: kconfig.h:8
ThreadQueue runnableQueue
Definition: sched.c:37
ThreadQueue waitQueue
Definition: sched.c:33
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:557
uint64_t ctxSwitches
Definition: thread.h:51
uint64_t tid
Definition: thread.h:36
Here is the call graph for this function:

◆ Handle_GlobalInit()

void Handle_GlobalInit ( )

Definition at line 15 of file handle.c.

16{
17 Slab_Init(&handleSlab, "Handle Objects", sizeof(Handle), 16);
18}
Slab handleSlab
Definition: handle.c:12
void Slab_Init(Slab *slab, const char *name, uintptr_t objsz, uintptr_t align)
Definition: handle.h:17
Here is the call graph for this function:
Here is the caller graph for this function:

◆ REGISTER_DBGCMD() [1/2]

REGISTER_DBGCMD ( threadinfo  ,
"Display current thread state"  ,
Debug_ThreadInfo   
)

◆ REGISTER_DBGCMD() [2/2]

REGISTER_DBGCMD ( threads  ,
"Display list of threads"  ,
Debug_Threads   
)

◆ Thread_Create()

Thread * Thread_Create ( Process proc)

Definition at line 96 of file thread.c.

97{
99
100 if (!thr)
101 return NULL;
102
103 memset(thr, 0, sizeof(*thr));
104
105 ASSERT(proc != NULL);
106
107 thr->tid = proc->nextThreadID++;
109 if (thr->kstack == 0) {
110 Slab_Free(&threadSlab, thr);
111 return NULL;
112 }
113
114 Process_Retain(proc);
115
116 Spinlock_Lock(&proc->lock);
117 thr->proc = proc;
118 proc->threads++;
119 TAILQ_INSERT_TAIL(&proc->threadList, thr, threadList);
120 thr->space = proc->space;
121 thr->ustack = proc->ustackNext;
123 Spinlock_Unlock(&proc->lock);
124
126 thr->timerEvt = NULL;
127 thr->refCount = 1;
128
129 Thread_InitArch(thr);
130 // Initialize queue
131
132 return thr;
133}
void Thread_InitArch(Thread *thr)
Definition: thread.c:20
void Process_Retain(Process *proc)
Definition: process.c:171
#define SCHED_STATE_NULL
Definition: thread.h:25
#define ASSERT(_x)
Definition: kassert.h:8
Slab threadSlab
Definition: thread.c:48
void Slab_Free(Slab *slab, void *obj)
Definition: slab.c:135
void * PAlloc_AllocPage()
Definition: palloc.c:188
void * Slab_Alloc(Slab *slab) __attribute__((malloc))
Definition: slab.c:105
#define MEM_USERSPACE_STKLEN
Definition: pmap.h:37
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:641
void Spinlock_Unlock(Spinlock *lock) __UNLOCK_EX(*lock)
Definition: spinlock.c:109
void Spinlock_Lock(Spinlock *lock) __LOCK_EX(*lock)
Definition: spinlock.c:75
#define NULL
Definition: stddef.h:6
void * memset(void *dst, int c, size_t len)
Definition: string.c:164
Spinlock lock
Definition: thread.h:68
ThreadQueue threadList
Definition: thread.h:87
uintptr_t ustackNext
Definition: thread.h:71
uint64_t nextThreadID
Definition: thread.h:70
uint64_t threads
Definition: thread.h:86
AS * space
Definition: thread.h:67
struct Process * proc
Definition: thread.h:39
uint64_t refCount
Definition: thread.h:37
uintptr_t ustack
Definition: thread.h:35
AS * space
Definition: thread.h:33
KTimerEvent * timerEvt
Definition: thread.h:44
int schedState
Definition: thread.h:42
uintptr_t kstack
Definition: thread.h:34
uint64_t uintptr_t
Definition: types.h:16
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Thread_Destroy()

static void Thread_Destroy ( Thread thr)
static

Definition at line 195 of file thread.c.

196{
197 Process *proc = thr->proc;
198
199 // Don't free kernel threads
200 ASSERT(proc->pid != 1);
201
202 // Free userspace stack
203
204 Spinlock_Lock(&proc->lock);
205 proc->threads--;
206 TAILQ_REMOVE(&proc->threadList, thr, threadList);
207 Spinlock_Unlock(&proc->lock);
208
209 // Free AS
210 PAlloc_Release((void *)thr->kstack);
211
212 // Release process handle
213 Process_Release(thr->proc);
214
215 Slab_Free(&threadSlab, thr);
216}
void Process_Release(Process *proc)
Definition: process.c:185
void PAlloc_Release(void *pg)
Definition: palloc.c:265
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:659
Definition: thread.h:65
uint64_t pid
Definition: thread.h:66
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Thread_Dump()

void Thread_Dump ( Thread thr)

Definition at line 328 of file thread.c.

329{
330 const char *states[] = {
331 "NULL",
332 "RUNNABLE",
333 "RUNNING",
334 "WAITING",
335 "ZOMBIE"
336 };
337
338 // Thread_DumpArch(thr)
339 kprintf("space %016llx\n", thr->space);
340 kprintf("kstack %016llx\n", thr->kstack);
341 kprintf("tid %llu\n", thr->tid);
342 kprintf("refCount %d\n", thr->refCount);
343 kprintf("state %s\n", states[thr->schedState]);
344 kprintf("ctxswtch %llu\n", thr->ctxSwitches);
345 kprintf("utime %llu\n", thr->userTime);
346 kprintf("ktime %llu\n", thr->kernTime);
347 kprintf("wtime %llu\n", thr->waitTime);
348 if (thr->proc) {
349 Process_Dump(thr->proc);
350 }
351}
void Process_Dump(Process *proc)
Definition: process.c:251
uint64_t kernTime
Definition: thread.h:53
uint64_t waitTime
Definition: thread.h:54
uint64_t userTime
Definition: thread.h:52
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Thread_Init()

void Thread_Init ( )

Definition at line 53 of file thread.c.

54{
55 nextProcessID = 1;
56
57 Slab_Init(&processSlab, "Process Objects", sizeof(Process), 16);
58 Slab_Init(&threadSlab, "Thread Objects", sizeof(Thread), 16);
59
60 Spinlock_Init(&procLock, "Process List Lock", SPINLOCK_TYPE_NORMAL);
62
66
68
69 // Kernel Process
71
72 // Create an thread object for current context
73 Process *proc = Process_Create(NULL, "init");
74 curProc[0] = Thread_Create(proc);
76}
#define SCHED_STATE_RUNNING
Definition: thread.h:27
Process * Process_Create(Process *parent, const char *title)
Definition: process.c:50
ProcessQueue processList
Definition: process.c:30
Thread * Thread_Create(Process *proc)
Definition: thread.c:96
uint64_t nextProcessID
Definition: process.c:29
void Handle_GlobalInit()
Definition: handle.c:15
Spinlock procLock
Definition: process.c:28
Spinlock schedLock
Definition: sched.c:29
Slab processSlab
Definition: process.c:33
Process * kernelProcess
Definition: thread.c:45
#define TAILQ_INIT(head)
Definition: queue.h:597
#define SPINLOCK_TYPE_NORMAL
Definition: spinlock.h:12
#define SPINLOCK_TYPE_RECURSIVE
Definition: spinlock.h:13
void Spinlock_Init(Spinlock *lock, const char *name, uint64_t type)
Definition: spinlock.c:43
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Thread_InitAP()

void Thread_InitAP ( )

Definition at line 79 of file thread.c.

80{
82
84
85 //PAlloc_Release((void *)thr->kstack);
86 //thr->kstack = 0;
87
88 curProc[CPU()] = apthr;
89}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Thread_KThreadCreate()

Thread * Thread_KThreadCreate ( void(*)(void *)  f,
void *  arg 
)

Definition at line 136 of file thread.c.

137{
139 if (!thr)
140 return NULL;
141
142 Thread_SetupKThread(thr, f, (uintptr_t)arg, 0, 0);
143
144 return thr;
145}
void Thread_SetupKThread(Thread *thr, void(*f)(), uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
Definition: thread.c:26
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Thread_Lookup()

Thread * Thread_Lookup ( Process proc,
uint64_t  tid 
)

Thread_Lookup –

Lookup a thread by TID and increment its reference count.

Parameters
[in]procProcess within which to find a specific thread.
[in]tidThread ID of the thread to find.
Return values
NULLif the thread isn't found.

Definition at line 229 of file thread.c.

230{
231 Thread *t;
232 Thread *thr = NULL;
233
234 Spinlock_Lock(&proc->lock);
235 TAILQ_FOREACH(t, &proc->threadList, threadList) {
236 if (t->tid == tid) {
237 Thread_Retain(t);
238 thr = t;
239 break;
240 }
241 }
242 Spinlock_Unlock(&proc->lock);
243
244 return thr;
245}
void Thread_Retain(Thread *thr)
Definition: thread.c:253
Here is the call graph for this function:

◆ Thread_Release()

void Thread_Release ( Thread thr)

Thread_Release –

Decrement the reference count for a given thread.

Definition at line 265 of file thread.c.

266{
267 ASSERT(thr->refCount != 0);
268 if (__sync_fetch_and_sub(&thr->refCount, 1) == 1) {
269 Thread_Destroy(thr);
270 }
271}
static void Thread_Destroy(Thread *thr)
Definition: thread.c:195
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Thread_Retain()

void Thread_Retain ( Thread thr)

Thread_Retain –

Increment the reference count for a given thread.

Definition at line 253 of file thread.c.

254{
255 ASSERT(thr->refCount != 0);
256 __sync_fetch_and_add(&thr->refCount, 1);
257}
Here is the caller graph for this function:

◆ Thread_UThreadCreate()

Thread * Thread_UThreadCreate ( Thread oldThr,
uint64_t  rip,
uint64_t  arg 
)

Definition at line 148 of file thread.c.

149{
150 Process *proc = oldThr->proc;
152
153 if (!thr)
154 return NULL;
155
156 memset(thr, 0, sizeof(*thr));
157
158 thr->tid = proc->nextThreadID++;
160 if (thr->kstack == 0) {
161 Slab_Free(&threadSlab, thr);
162 return NULL;
163 }
164
165 thr->space = oldThr->space;
167 thr->refCount = 1;
168
169 Spinlock_Lock(&proc->lock);
170 thr->ustack = proc->ustackNext;
172 Spinlock_Unlock(&proc->lock);
173
175 // XXX: Check failure
176
177 Thread_InitArch(thr);
178 // Initialize queue
179
180 Thread_SetupUThread(thr, rip, arg);
181
182 Process_Retain(proc);
183
184 Spinlock_Lock(&proc->lock);
185 thr->proc = proc;
186 // XXX: Process lock
187 proc->threads++;
188 TAILQ_INSERT_TAIL(&proc->threadList, thr, threadList);
189 Spinlock_Unlock(&proc->lock);
190
191 return thr;
192}
void Thread_SetupUThread(Thread *thr, uintptr_t rip, uintptr_t arg)
Definition: thread.c:75
#define PTE_W
Definition: amd64.h:36
bool PMap_AllocMap(AS *as, uint64_t virt, uint64_t len, uint64_t flags)
Definition: pmap.c:423
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Thread_Wait()

uint64_t Thread_Wait ( Thread thr,
uint64_t  tid 
)

Thread_Wait –

Wait for any thread (tid == TID_ANY) or a specific thread.

Definition at line 279 of file thread.c.

280{
281 Thread *t;
282 uint64_t status;
283
284 ASSERT(thr->proc != NULL);
285
286 if (tid == TID_ANY) {
287 t = TAILQ_FIRST(&thr->proc->zombieQueue);
288 if (!t) {
289 return SYSCALL_PACK(EAGAIN, 0);
290 }
291
292 TAILQ_REMOVE(&thr->proc->zombieQueue, t, schedQueue);
293 status = t->exitValue;
295 return SYSCALL_PACK(0, status);
296 }
297
298 // XXXURGENT
299 TAILQ_FOREACH(t, &thr->proc->zombieQueue, schedQueue) {
300 if (t->tid == tid) {
301 TAILQ_REMOVE(&thr->proc->zombieQueue, t, schedQueue);
302 status = t->exitValue;
304 return SYSCALL_PACK(0, status);
305 }
306 }
307
308 return 0;
309}
#define EAGAIN
Definition: errno.h:19
#define TID_ANY
Definition: thread.h:106
void Thread_Release(Thread *thr)
Definition: thread.c:265
#define TAILQ_FIRST(head)
Definition: queue.h:555
ThreadQueue zombieQueue
Definition: thread.h:89
uintptr_t exitValue
Definition: thread.h:45
#define SYSCALL_PACK(_errcode, _val)
Definition: syscall.h:55
unsigned long uint64_t
Definition: types.h:13
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ThreadKThreadEntry()

void ThreadKThreadEntry ( TrapFrame tf)

Definition at line 314 of file thread.c.

315{
316 TSS[CPU()].rsp0 = curProc[CPU()]->kstack + 4096;
317
319
320 Trap_Pop(tf);
321}
TaskStateSegment64 TSS[MAX_CPUS]
Definition: machine.c:40
uint64_t rsp0
Definition: amd64.h:108
void Trap_Pop(TrapFrame *tf)
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ curProc

Thread* curProc[MAX_CPUS]
extern

Current thread executing on a given CPU.

Definition at line 41 of file sched.c.

◆ kernelProcess

Process* kernelProcess

Definition at line 45 of file thread.c.

◆ nextProcessID

uint64_t nextProcessID
extern

Definition at line 29 of file process.c.

◆ processList

ProcessQueue processList
extern

Definition at line 30 of file process.c.

◆ processSlab

Slab processSlab
extern

Definition at line 33 of file process.c.

◆ procLock

Spinlock procLock
extern

Definition at line 28 of file process.c.

◆ runnableQueue

ThreadQueue runnableQueue
extern

All runnable threads.

Definition at line 37 of file sched.c.

◆ schedLock

Spinlock schedLock
extern

Scheduler lock that protects all queues.

Definition at line 29 of file sched.c.

◆ threadSlab

Slab threadSlab

Definition at line 48 of file thread.c.

◆ TSS

Definition at line 40 of file machine.c.

◆ waitQueue

ThreadQueue waitQueue
extern

All threads currently waiting.

Definition at line 33 of file sched.c.