CS350 COS
COS
Loading...
Searching...
No Matches
process.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013-2023 Ali Mashtizadeh
3 * All rights reserved.
4 */
5
6#include <stdbool.h>
7#include <stdint.h>
8#include <string.h>
9
10#include <errno.h>
11#include <sys/syscall.h>
12
13#include <sys/kassert.h>
14#include <sys/kconfig.h>
15#include <sys/kdebug.h>
16#include <sys/kmem.h>
17#include <sys/ktime.h>
18#include <sys/mp.h>
19#include <sys/spinlock.h>
20#include <sys/thread.h>
21
22#include <machine/trap.h>
23#include <machine/pmap.h>
24
25extern Thread *curProc[MAX_CPUS];
26
27// Process List
30ProcessQueue processList;
31
32// Memory Pools
34
35/*
36 * Process
37 */
38
49Process *
50Process_Create(Process *parent, const char *title)
51{
53
54 if (!proc)
55 return NULL;
56
57 memset(proc, 0, sizeof(*proc));
58
59 proc->pid = nextProcessID++;
60 proc->threads = 0;
61 proc->refCount = 1;
63 TAILQ_INIT(&proc->threadList);
64
65 if (title) {
66 strncpy((char *)&proc->title, title, PROCESS_TITLE_LENGTH);
67 } else {
68 proc->title[0] = '\0';
69 }
70
71 proc->space = PMap_NewAS();
72 if (proc->space == NULL) {
73 Slab_Free(&processSlab, proc);
74 return NULL;
75 }
77
78 Spinlock_Init(&proc->lock, "Process Lock", SPINLOCK_TYPE_NORMAL);
79
80 Semaphore_Init(&proc->zombieSemaphore, 0, "Zombie Semaphore");
81 TAILQ_INIT(&proc->zombieQueue);
82
83 Handle_Init(proc);
84
85 proc->parent = parent;
86 if (parent) {
87 Spinlock_Lock(&parent->lock);
88 TAILQ_INSERT_TAIL(&parent->childrenList, proc, siblingList);
89 Spinlock_Unlock(&parent->lock);
90 }
92 TAILQ_INIT(&proc->zombieProc);
93 Mutex_Init(&proc->zombieProcLock, "Zombie Process Lock");
94 CV_Init(&proc->zombieProcCV, "Zombie Process CV");
95 CV_Init(&proc->zombieProcPCV, "Zombie Process PCV");
96
100
101 return proc;
102}
103
112static void
114{
115 Handle_Destroy(proc);
116
117 Spinlock_Destroy(&proc->lock);
120 CV_Destroy(&proc->zombieProcCV);
122 PMap_DestroyAS(proc->space);
123
124 // XXX: We need to promote zombie processes to our parent
125 // XXX: Release the semaphore as well
126
130
131 Slab_Free(&processSlab, proc);
132}
133
144Process *
146{
147 Process *p;
148 Process *proc = NULL;
149
152 if (p->pid == pid) {
154 proc = p;
155 break;
156 }
157 }
159
160 return proc;
161}
162
170void
172{
173 ASSERT(proc->refCount != 0);
174 __sync_fetch_and_add(&proc->refCount, 1);
175}
176
184void
186{
187 ASSERT(proc->refCount != 0);
188 if (__sync_fetch_and_sub(&proc->refCount, 1) == 1) {
189 Process_Destroy(proc);
190 }
191}
192
207{
208 Thread *thr;
209 Process *p = NULL;
210 uint64_t status;
211
212 // XXXFILLMEIN
213 /*
214 * Dummy waitpid implementation that pretends the
215 * process has already exited. Remove and replace
216 * with the actual implementation from the assignment
217 * description.
218 */
219 /* XXXREMOVE START */
220 ASSERT(pid != 0);
221 return (pid << 16);
222 /* XXXREMOVE END */
223
224 status = (p->pid << 16) | (p->exitCode & 0xff);
225
226 // Release threads
227 Spinlock_Lock(&proc->lock);
228 while (!TAILQ_EMPTY(&p->zombieQueue)) {
229 thr = TAILQ_FIRST(&p->zombieQueue);
230 TAILQ_REMOVE(&p->zombieQueue, thr, schedQueue);
231 Spinlock_Unlock(&proc->lock);
232
233 ASSERT(thr->proc->pid != 1);
234 Thread_Release(thr);
235
236 Spinlock_Lock(&proc->lock);
237 }
238 Spinlock_Unlock(&proc->lock);
239
240 // Release process
242
243 return SYSCALL_PACK(0, status);
244}
245
246/*
247 * Debugging
248 */
249
250void
252{
253 const char *stateStrings[] = {
254 "NULL",
255 "READY",
256 "ZOMBIE"
257 };
258
259 kprintf("title %s\n", proc->title);
260 kprintf("pid %llu\n", proc->pid);
261 kprintf("state %s\n", stateStrings[proc->procState]);
262 kprintf("space %016llx\n", proc->space);
263 kprintf("threads %llu\n", proc->threads);
264 kprintf("refCount %d\n", proc->refCount);
265 kprintf("nextFD %llu\n", proc->nextFD);
266}
267
268static void
269Debug_Processes(int argc, const char *argv[])
270{
271 Process *proc;
272
273 /*
274 * We don't hold locks in case you the kernel debugger is entered while
275 * holding this lock.
276 */
277 //Spinlock_Lock(&threadLock);
278
280 {
281 kprintf("Process: %d(%016llx)\n", proc->pid, proc);
282 Process_Dump(proc);
283 }
284
285 //Spinlock_Unlock(&threadLock);
286}
287
288REGISTER_DBGCMD(processes, "Display list of processes", Debug_Processes);
289
290static void
291Debug_ProcInfo(int argc, const char *argv[])
292{
293 Thread *thr = curProc[CPU()];
294
295 kprintf("Current Process State:\n");
296 Process_Dump(thr->proc);
297}
298
299REGISTER_DBGCMD(procinfo, "Display current process state", Debug_ProcInfo);
300
void CV_Destroy(CV *cv)
Definition: cv.c:33
void CV_Init(CV *cv, const char *name)
Definition: cv.c:25
#define CPU
Definition: mp.h:7
void Handle_Init(Process *proc)
Definition: handle.c:23
void Thread_Release(Thread *thr)
Definition: thread.c:265
#define PROC_STATE_NULL
Definition: thread.h:61
void Handle_Destroy(Process *proc)
Definition: handle.c:33
#define PROCESS_TITLE_LENGTH
Definition: thread.h:59
#define ASSERT(_x)
Definition: kassert.h:8
int kprintf(const char *fmt,...)
Definition: printf.c:210
#define MAX_CPUS
Definition: kconfig.h:8
#define REGISTER_DBGCMD(_NAME, _DESC, _FUNC)
Definition: kdebug.h:11
void Slab_Free(Slab *slab, void *obj)
Definition: slab.c:135
void * Slab_Alloc(Slab *slab) __attribute__((malloc))
Definition: slab.c:105
AS * PMap_NewAS()
Definition: pmap.c:80
#define MEM_USERSPACE_STKBASE
Definition: pmap.h:36
void PMap_DestroyAS(AS *space)
Definition: pmap.c:116
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:557
#define TAILQ_INIT(head)
Definition: queue.h:597
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:641
#define TAILQ_FIRST(head)
Definition: queue.h:555
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:659
#define TAILQ_EMPTY(head)
Definition: queue.h:553
void Semaphore_Destroy(Semaphore *sema)
Definition: semaphore.c:39
void Semaphore_Init(Semaphore *sema, int count, const char *name)
void Spinlock_Unlock(Spinlock *lock) __UNLOCK_EX(*lock)
Definition: spinlock.c:109
#define SPINLOCK_TYPE_NORMAL
Definition: spinlock.h:12
void Spinlock_Destroy(Spinlock *lock)
Definition: spinlock.c:61
void Spinlock_Lock(Spinlock *lock) __LOCK_EX(*lock)
Definition: spinlock.c:75
void Spinlock_Init(Spinlock *lock, const char *name, uint64_t type)
Definition: spinlock.c:43
#define NULL
Definition: stddef.h:6
char * strncpy(char *to, const char *from, size_t len)
Definition: string.c:34
void * memset(void *dst, int c, size_t len)
Definition: string.c:164
Definition: thread.h:65
uint64_t nextFD
Definition: thread.h:91
Spinlock lock
Definition: thread.h:68
uint64_t refCount
Definition: thread.h:73
ProcessQueue zombieProc
Definition: thread.h:81
ThreadQueue threadList
Definition: thread.h:87
uintptr_t ustackNext
Definition: thread.h:71
uint64_t exitCode
Definition: thread.h:76
char title[PROCESS_TITLE_LENGTH]
Definition: thread.h:74
ThreadQueue zombieQueue
Definition: thread.h:89
uint64_t threads
Definition: thread.h:86
Process * parent
Definition: thread.h:78
Semaphore zombieSemaphore
Definition: thread.h:88
CV zombieProcPCV
Definition: thread.h:84
Mutex zombieProcLock
Definition: thread.h:82
int procState
Definition: thread.h:75
CV zombieProcCV
Definition: thread.h:83
ProcessQueue childrenList
Definition: thread.h:80
uint64_t pid
Definition: thread.h:66
AS * space
Definition: thread.h:67
Definition: kmem.h:46
Definition: thread.h:31
struct Process * proc
Definition: thread.h:39
void Mutex_Destroy(Mutex *mtx)
Definition: mutex.c:39
void Mutex_Init(Mutex *mtx, const char *name)
Definition: mutex.c:30
#define SYSCALL_PACK(_errcode, _val)
Definition: syscall.h:55
ProcessQueue processList
Definition: process.c:30
uint64_t nextProcessID
Definition: process.c:29
Process * Process_Create(Process *parent, const char *title)
Definition: process.c:50
void Process_Dump(Process *proc)
Definition: process.c:251
Thread * curProc[MAX_CPUS]
Definition: sched.c:41
static void Debug_Processes(int argc, const char *argv[])
Definition: process.c:269
Process * Process_Lookup(uint64_t pid)
Definition: process.c:145
uint64_t Process_Wait(Process *proc, uint64_t pid)
Definition: process.c:206
void Process_Retain(Process *proc)
Definition: process.c:171
Spinlock procLock
Definition: process.c:28
static void Debug_ProcInfo(int argc, const char *argv[])
Definition: process.c:291
static void Process_Destroy(Process *proc)
Definition: process.c:113
void Process_Release(Process *proc)
Definition: process.c:185
Slab processSlab
Definition: process.c:33
unsigned long uint64_t
Definition: types.h:13