extern void trapMemory(ExceptionStackFrame *exceptionStackFrame) { TracePrintf(512, "trapMemory: vector(%d), code(%d), addr(%d), psr(%d), pc(%d), sp(%d), regs(%s)\n", exceptionStackFrame->vector, exceptionStackFrame->code, exceptionStackFrame->addr, exceptionStackFrame->psr, exceptionStackFrame->pc, exceptionStackFrame->sp, exceptionStackFrame->regs); if( exceptionStackFrame -> addr > current -> stack_brk ) { TracePrintf(0, "Trap Memory Error: addr: %d is large than stack_brk: %d\n", exceptionStackFrame -> addr, current -> stack_brk); //Exit; } if( exceptionStackFrame -> addr < UP_TO_PAGE(current -> heap_brk) + PAGESIZE ) { TracePrintf(0, "Trap Memory Error: addr: %d is smaller than heap_brk: %d\n", exceptionStackFrame -> addr, current -> heap_brk); //Exit; } long userTablePTE; TracePrintf(510, "Moving user stack down to address: %d (%d)\n", exceptionStackFrame -> addr, (long)exceptionStackFrame -> addr >> PAGESHIFT); for (userTablePTE = (DOWN_TO_PAGE(exceptionStackFrame -> addr)); userTablePTE < (DOWN_TO_PAGE(current -> stack_brk)); userTablePTE += PAGESIZE) { unsigned int i = ((userTablePTE) >> PAGESHIFT) % PAGE_TABLE_LEN; UserPageTable[i].valid = 1; UserPageTable[i].uprot = PROT_NONE; UserPageTable[i].kprot = PROT_READ | PROT_WRITE; /* Need to change the pfn here */ UserPageTable[i].pfn = allocatePhysicalPage(); TracePrintf(250, "Allocate physical pages for user process: PID(%d), VPN(%d), PFN(%d).\n", current -> PID, i, UserPageTable[i].pfn); } }
void DoDelay(UserContext *context) { TracePrintf(1, "in DoDelay\n"); current_process->clock_count = context->regs[0]; TracePrintf(1, "Delay: %d\n", context->regs[0]); DelayAdd(current_process); LoadNextProc(context, BLOCK); }
void LoadNextProc(UserContext *context, int block) { DelayPop(); if (!queueIsEmpty(ready_queue)) { if (current_process) { current_process->user_context = *context; if (block == NO_BLOCK) { queuePush(ready_queue, current_process); } } PCB *next = queuePop(ready_queue); TracePrintf(1, "LoadNextProc: Next Process Id: %d\n", next->id); if(next->id == 2) TracePrintf(3, "LoadNextProc: PCB has %p child\n", next->parent->children->head); WriteRegister(REG_PTBR1, (unsigned int) &(next->cow.pageTable)); WriteRegister(REG_TLB_FLUSH, TLB_FLUSH_1); KernelContextSwitch(MyKCS, current_process, next); TracePrintf(1, "LoadNextProc: Got past MyKCS\n"); *context = current_process->user_context; TracePrintf(3, "LoadNextProc: current user context pc is %p\n", context->pc); } }
/* This function make perfect mapping from kernel virtual memory phyical memory */ void init_kernel_page_table() { kernel_page_table = (pte_t*) malloc(sizeof(pte_t) * GET_PAGE_NUMBER(VMEM_0_SIZE)); // For text segment mapping TracePrintf(0, "Text Start=%p, End=%p\n", kernel_memory.text_low, kernel_memory.data_low); write_kernel_pte(kernel_memory.text_low, kernel_memory.data_low , _VALID, PROT_READ | PROT_EXEC); // For data segment mapping TracePrintf(0, "Data Start=%p, End=%p\n", kernel_memory.data_low, kernel_memory.brk_low); write_kernel_pte(kernel_memory.data_low, kernel_memory.brk_low , _VALID, PROT_READ | PROT_WRITE); // For stack segment mapping, noted that stack space is reserved even if it is not used TracePrintf(0, "Stack Start=%p, End=%p\n", KERNEL_STACK_BASE, KERNEL_STACK_LIMIT); write_kernel_pte(KERNEL_STACK_BASE, KERNEL_STACK_LIMIT , _VALID, PROT_READ | PROT_WRITE); int i; // Add free pages between heap and stack int start_pfn = GET_PAGE_NUMBER(UP_TO_PAGE(kernel_memory.brk_high)); int end_pfn = GET_PAGE_NUMBER(DOWN_TO_PAGE(KERNEL_STACK_BASE)); for(i = start_pfn; i < end_pfn; i++) { add_tail_available_frame(i); } // Add free pages above kernel space start_pfn = GET_PAGE_NUMBER(UP_TO_PAGE(VMEM_0_LIMIT)); end_pfn = GET_PAGE_NUMBER(DOWN_TO_PAGE(PMEM_BASE)) + PAGE_SIZE; for(i = start_pfn; i < end_pfn; i++) { add_tail_available_frame(i); } }
void DoLockInit(UserContext *context) { if (BufferCheck(context->regs[0], INT_LENGTH) == ERROR || BufferWriteCheck(context->regs[0], INT_LENGTH) == ERROR) { TracePrintf(1, "DoLockInit: Pointer given not valid. Returning Error\n"); context->regs[0] = ERROR; return; } Lock *lock = malloc(sizeof(Lock)); if (lock == NULL) { TracePrintf(2, "CreateLock, malloc error\n"); context->regs[0] = ERROR; return; } lock->waiting = queueNew(); if (lock->waiting == NULL) { TracePrintf(2, "CreateLock: malloc error\n"); context->regs[0] = ERROR; return; } lock->cvars = 0; int lock_id = lock_count * NUM_RESOURCE_TYPES + LOCK; lock_count++; lock->id = lock_id; *((int *) context->regs[0]) = lock_id; queuePush(locks, lock); context->regs[0] = SUCCESS; }
extern int KernelBrk(void *addr, struct PCBNode *pcb) { TracePrintf(256, "Brk: addr(%d)\n", addr); //check if the addr is illegal if(addr < MEM_INVALID_SIZE) { TracePrintf(0, "Error in KernelBrk: Trying to set the brk below MEM_INVALID_SIZE.\n"); //Exit the program. } if(addr > DOWN_TO_PAGE(pcb -> stack_brk) - PAGESIZE) { TracePrintf(0, "Error in KernelBrk: Trying to set the brk inside or above the red zone.\n"); } unsigned int userTablePTE; //Only allocate for entire pages?? unsigned int gap = (UP_TO_PAGE(addr)-UP_TO_PAGE(pcb -> heap_brk)); if(gap>0) { TracePrintf(250, "Moving user brk up to address: %d (%d)\n", addr, (long)addr >> PAGESHIFT); for (userTablePTE = (UP_TO_PAGE(pcb -> heap_brk)); userTablePTE < (UP_TO_PAGE(addr)); userTablePTE += PAGESIZE) { unsigned int i = ((userTablePTE) >> PAGESHIFT) % PAGE_TABLE_LEN; UserPageTable[i].valid = 1; UserPageTable[i].uprot = PROT_NONE; UserPageTable[i].kprot = PROT_READ | PROT_WRITE; /* Need to change the pfn here */ UserPageTable[i].pfn = allocatePhysicalPage(); TracePrintf(250, "Allocate physical pages for user process: PID(%d), VPN(%d), PFN(%d).\n", pcb -> PID, i, UserPageTable[i].pfn); } }
extern int KernelFork(void) { TracePrintf(256, "Fork\n"); struct PCBNode cur_active = *active_process; struct PCBNode* newproc = malloc(sizeof(struct PCBNode)); if(newproc == NULL) return ERROR; newproc = (struct PCBNode *)malloc(sizeof(struct PCBNode)); newproc -> PID = nextPID(); //will need to change this thing later newproc -> pageTable = malloc(PAGE_TABLE_LEN * sizeof(struct pte)); newproc -> status = READY; newproc -> blockedReason = 0; newproc -> numTicksRemainForDelay = 0; newproc -> parent = NULL; newproc -> child = NULL; newproc -> prevSibling = NULL; newproc -> nextSibling = NULL; TracePrintf(100, "Fork enter context switch\n"); ContextSwitch(forkSwitchFunc, &(cur_active.ctxp), &cur_active, newproc); TracePrintf(100, "Fork left context switch\n"); if(cur_active.PID == active_process->PID){ //return from parent return newproc->PID; }else{ //this is returning from child, which means we should maintain the child queue return 0; } return 0; }
void DoWait(UserContext *context) { if (BufferCheck(context->regs[0], INT_LENGTH) == ERROR || BufferWriteCheck(context->regs[0], INT_LENGTH) == ERROR) { TracePrintf(1, "DoWait: Pointer given not valid. Returning Error\n"); context->regs[0] = ERROR; return; } if (queueIsEmpty(current_process->children) && queueIsEmpty(current_process->deadChildren)) { TracePrintf(2, "DoWait: PCB %d Has no children. Returning Error.\n", current_process->id); TracePrintf(2, "DoWait: Children queue count: %d, deadChildren count: %d\n", current_process->children->length, current_process->deadChildren->length); context->regs[0] = ERROR; } else { if (queueIsEmpty(current_process->deadChildren)) { current_process->status = WAITING; queuePush(wait_queue, current_process); LoadNextProc(context, BLOCK); } ZCB *child = queuePop(current_process->deadChildren); queueRemove(process_queue, child); *((int *)context->regs[0]) = child->status; context->regs[0] = child->id; } }
int main(int argc, char *argv[]) { TracePrintf(1, "\t===>Start: tty.c.c\n"); char write_msg[] = "Hello World!"; int size = sizeof(write_msg); int rc; rc = Fork(); if (rc == 0) { Pause(); Pause(); Pause(); Pause(); TtyWrite(1, write_msg, size); TracePrintf(1, "\t===>tty.c: Just wrote to terminal 1.\n"); return 0; } else { char read_msg[10]; size = sizeof(read_msg); TtyRead(2, read_msg, size); TracePrintf(1, "\t===>tty.c: Just read from terminal 2: %s.\n", read_msg); } TracePrintf(1, "\t===>End: tty.c.c\n"); return 0; }
void DoIdle(void) { while(1) { TracePrintf(0, "********************************************************************************\n"); TracePrintf(0, "*************************** DoIlde is running! *******************************\n"); TracePrintf(0, "********************************************************************************\n"); Pause(); } }
int queueIsEmpty(Queue *queue) { TracePrintf(4, "queueIsEmpty: queue->head = %p, queue->length = %d\n", queue->head, queue->length); if (queue->head == NULL) { TracePrintf(4, "queueIsEmpty: queue is empty\n"); } return (queue->head == NULL); }
// Print error message and kill proc void TrapIllegal(UserContext *user_context) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> TrapIllegal(%p)\n", user_context); char *err_str = calloc(TERMINAL_MAX_LINE, sizeof(char)); sprintf(err_str, "TRAP_ILLEGAL exception for proc %d\n", current_proc->pid); KernelTtyWriteInternal(0, err_str, strnlen(err_str, TERMINAL_MAX_LINE), user_context); free(err_str); KernelExit(ERROR, user_context); TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< TrapIllegal(%p)\n", user_context); }
// Get a copy of the currently running Kernel Context and save it in the current pcb KernelContext *SaveCurrentKernelContext(KernelContext *kernel_context, void *current_pcb, void *next_pcb) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> SaveCurrentKernelContext()\n"); ((PCB*) current_pcb)->kernel_context = *kernel_context; TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< SaveCurrentKernelContext()\n"); return kernel_context; }
void TrapTtyRecieve(UserContext *user_context) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> TrapTtyRecieve(%p)\n", user_context); int tty_id = user_context->code; // Find the proper terminal struct Tty term = ttys[tty_id]; if (ListEmpty(term.waiting_to_receive)) { // no waiting procs, so create line buffer and // add to list LineBuffer *lb = calloc(1, sizeof(LineBuffer)); lb->buffer = calloc(TERMINAL_MAX_LINE, sizeof(char)); lb->length = TtyReceive(tty_id, lb->buffer, TERMINAL_MAX_LINE); ListEnqueue(term.line_buffers, lb, 0); } else { // at least one proc waiting // create heap in kernel to use char *input = calloc(TERMINAL_MAX_LINE, sizeof(char)); char *input_ptr = input; // point how far into the buffer we've read int input_length = TtyReceive(tty_id, input, TERMINAL_MAX_LINE); int input_remaining = input_length; // Continue so long as procs are waiting and there is unconsumed input while (!ListEmpty(term.waiting_to_receive) && input_remaining > 0) { PCB *waiting_proc = (PCB *) ListDequeue(term.waiting_to_receive); assert(waiting_proc->tty_receive_buffer); // put proc back into ready queue ListAppend(ready_queue, waiting_proc, waiting_proc->pid); if (input_remaining <= waiting_proc->tty_receive_len) { // Consuming all the input memcpy(waiting_proc->tty_receive_buffer, input_ptr, input_remaining); waiting_proc->tty_receive_len = input_remaining; input_remaining = 0; } else { // Only consuming some of the input memcpy(waiting_proc->tty_receive_buffer, input_ptr, waiting_proc->tty_receive_len); input_remaining -= waiting_proc->tty_receive_len; input_ptr += waiting_proc->tty_receive_len; } } // Check if there is still input left after all the procs have been filled if (input_remaining > 0) { // Create new line buffer and store char *remaining_buff = calloc(input_remaining, sizeof(char)); memcpy(remaining_buff, input_ptr, input_remaining); LineBuffer *lb = calloc(1, sizeof(LineBuffer)); lb->buffer = remaining_buff; lb->length = input_remaining; ListEnqueue(term.line_buffers, lb, 0); } free(input); } TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< TrapTtyRecieve(%p)\n", user_context); }
// Print message and kill void TrapMath(UserContext *user_context) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> TrapMath(%p)\n", user_context); TracePrintf(TRACE_LEVEL_NON_TERMINAL_PROBLEM, "Killing proc on trap math \n"); char *err_str = calloc(TERMINAL_MAX_LINE, sizeof(char)); sprintf(err_str, "TRAP_MATH exception for proc %d\n", current_proc->pid); KernelTtyWriteInternal(0, err_str, strnlen(err_str, TERMINAL_MAX_LINE), user_context); free(err_str); KernelExit(ERROR, user_context); TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< TrapMath(%p)\n", user_context); }
void DoExec(UserContext *context) { TracePrintf(5, "DoExec\n"); current_process->user_context = *context; TracePrintf(5, "DoExec: LoadProgram\n"); int rc = LoadProgram(context->regs[0], context->regs[1], current_process); TracePrintf(5, "DoExec: finished LoadProgram\n"); if (rc != SUCCESS) { current_process->user_context.regs[0] = ERROR; } *context = current_process->user_context; TracePrintf(5, "Finished DoExec\n"); }
void DoPS(UserContext *context) { TracePrintf(3, "DoPS: In DoPS\n"); for (List *process = process_queue->head; process; process = process->next) { if (((ZCB *) process->data)->status == DEAD) { TracePrintf(1, "PID: %d. DEAD\n", ((ZCB *) process->data)->id); } else { TracePrintf(1, "PID: %d.\n", ((PCB *) process->data)->id); } } context->regs[0] = SUCCESS; return; }
int main(int argc, char **argv) { int i; TracePrintf(-1, "In process %d\n", GetPid()); printf("In process %d\n", GetPid()); TracePrintf(-1, "%d arguments passed in\n", argc); printf("%d arguments passed in\n", argc); for (i = 0; i < argc; i++) { TracePrintf(-1, "\targ %d is %s\n", i, argv[i]); printf("\targ %d is %s\n", i, argv[i]); } return 0; }
// Context switch to the next process in the ready queue. // The next process's context will be loaded into the param user_context. // NOTE: place the current proc into the correct queue before calling // (e.g., ready queue, clock blocked queue) void SwitchToNextProc(UserContext *user_context) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> SwitchToNextProc()\n"); // Get the proc at the front of the queue PCB *next_proc = ListDequeue(ready_queue); if (next_proc) { SwitchToProc(next_proc, user_context); } else { // No procs waiting, so just switch to the idle proc TracePrintf(TRACE_LEVEL_DETAIL_INFO, "No waiting procs, idling\n"); SwitchToProc(idle_proc, user_context); } TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< SwitchToNextProc()\n"); }
int main(int argc, char *argv[]) { TracePrintf(1, "\t===>pipe.c\n"); int pipe_id; int rc; if (PipeInit(&pipe_id) != 0) TracePrintf(1, "Failed to initialize pipe\n"); else TracePrintf(1, "Pipe Initialized. ID = %d\n", pipe_id); rc = Fork(); if (rc == 0) { char *to_write = (char *)malloc(5 * sizeof(char)); to_write[0] = 'a'; to_write[1] = 'b'; to_write[2] = 'c'; to_write[3] = 'd'; to_write[4] = 'e'; char *second_write = (char *)malloc(2 * sizeof(char)); second_write[0] = 'e'; second_write[1] = 'f'; int written; Pause(); TracePrintf(1, "\tCHILD: about to write to the lock\n"); written = PipeWrite(pipe_id, to_write, 4); TracePrintf(1, "\tCHILD: wrote %d characters to the lock\n", written); Pause(); TracePrintf(1, "\tCHILD: pausing once\n"); Pause(); written = PipeWrite(pipe_id, second_write, 2); TracePrintf(1, "\tCHILD: wrote to the pipe again (%d chars)\n", written); Pause(); Exit(0); } else { char *to_read = (char *)malloc(6 * sizeof(char)); int read; Pause(); Pause(); TracePrintf(1, "\tPARENT: reading 6 chars from the pipe (before it's ready\n"); read = PipeRead(pipe_id, to_read, 6); TracePrintf(1, "\tPARENT: read %d chars from the pipe. Results: %s\n", read, to_read); Pause(); Exit(0); } return 0; }
// Method pased to ListMap on clock tick // decrements the number of ticks remaining for each proc that is waiting from Delay void DecrementTicksRemaining(void *_proc) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> DecrementTicksRemaining(%p)\n", _proc); PCB *proc = (PCB *) _proc; --proc->clock_ticks_until_ready; if (proc->clock_ticks_until_ready <= 0) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> DecrementTicksRemaining: proc %p done waiting!\n", _proc); ListRemoveById(clock_block_procs, proc->pid); ListAppend(ready_queue, proc, proc->pid); } TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< DecrementTicksRemaining()\n"); }
void TrapTtyTransmit(UserContext *user_context) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> TrapTtyTransmit(%p)\n", user_context); int tty_id = user_context->code; Tty term = ttys[tty_id]; assert(!ListEmpty(term.waiting_to_transmit)); // Get the currently transmitting proc (always at the front of the list) PCB *waiting_proc = (PCB *) ListPeak(term.waiting_to_transmit); if (waiting_proc->tty_transmit_len > TERMINAL_MAX_LINE) { // not completely transmitted, so handle pointer stuff and leave in // front of the queue waiting_proc->tty_transmit_pointer += TERMINAL_MAX_LINE; waiting_proc->tty_transmit_len -= TERMINAL_MAX_LINE; // transmit min(MAX_LINE, len) if (TERMINAL_MAX_LINE > waiting_proc->tty_transmit_len) { TtyTransmit(tty_id, waiting_proc->tty_transmit_pointer, waiting_proc->tty_transmit_len); } else { TtyTransmit(tty_id, waiting_proc->tty_transmit_pointer, TERMINAL_MAX_LINE); } return; } // transmission complete // since done, take off transmitting list ListRemoveById(term.waiting_to_transmit, waiting_proc->pid); ListAppend(ready_queue, waiting_proc, waiting_proc->pid); free(waiting_proc->tty_transmit_buffer); if (ListEmpty(term.waiting_to_transmit)) { return; // no other procs waiting on this term } // Get the next proc waiting to submit PCB *next_to_transmit = (PCB *) ListPeak(term.waiting_to_transmit); // transmit min(MAX_LINE, len) if (TERMINAL_MAX_LINE > next_to_transmit->tty_transmit_len) { TtyTransmit(tty_id, next_to_transmit->tty_transmit_pointer, next_to_transmit->tty_transmit_len); } else { TtyTransmit(tty_id, next_to_transmit->tty_transmit_pointer, TERMINAL_MAX_LINE); } TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< TrapTtyTransmit(%p)\n", user_context); }
int LockRelease(Lock *lock) { if (lock == NULL) { TracePrintf(2, "LockRelease: Lock not found.\n"); return ERROR; } else if (lock->owner != current_process) { TracePrintf(2, "LockRelease: Current process does not hold lock it is trying to release.\n"); return ERROR; } else { lock->owner = queuePop(lock->waiting); if (lock->owner) { queuePush(ready_queue, lock->owner); } return SUCCESS; } }
void main(void) { int delay = 4; int delays[512]; int delays2[1024]; //int delays3[1024 * 2]; //int delays4[1024 * 4]; //int delays5[1024 * 8]; while(1) { TracePrintf(1, "GJJ is coding like a boss.\n"); // Delay(delay); Pause(); } TracePrintf(1, "GJJ leaving the init proc\n"); return; }
void TrapClock(UserContext *user_context) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> TrapClock(%p)\n", user_context); // Use Map interface to decrement the ticks remaining for each proc ListMap(clock_block_procs, &DecrementTicksRemaining); // If the current proc is not the idle, place it in the ready queue if (current_proc->pid != IDLE_PID) { ListAppend(ready_queue, current_proc, current_proc->pid); } // and switch to the next ready proc SwitchToNextProc(user_context); TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< TrapClock(%p)\n", user_context); }
extern void trapIllegal(ExceptionStackFrame *exceptionStackFrame) { TracePrintf(512, "trapIllegal: vector(%d), code(%d), addr(%d), psr(%d), pc(%d), sp(%d), regs(%s)\n", exceptionStackFrame->vector, exceptionStackFrame->code, exceptionStackFrame->addr, exceptionStackFrame->psr, exceptionStackFrame->pc, exceptionStackFrame->sp, exceptionStackFrame->regs); int code = exceptionStackFrame->code; char string[128]; char* msg = string; if (code == ILL_BADSTK) msg = "Bad stack\n"; else if (code == ILL_ILLOPC || code == ILL_ILLOPN || code == ILL_ILLADR) msg = "Illegal instruction\n"; else if (code == ILL_PRVOPC || code == ILL_PRVREG) msg = "Privileged instruction\n"; else if (code == ILL_COPROC) msg = "Coprocessor error\n"; else if (code == ILL_ILLTRP) msg = "Illegal software trap\n"; else if (code == BUS_ADRALN + 20) printf(msg, "Invalid address alignment %p", exceptionStackFrame->addr); else if (code == SI_KERNEL) msg = "Linux kernel SIGILL\n"; else if (code == SI_USER) msg = "Received SIGILL from user\n"; else printf(msg, "Unknown code 0x%x", code); //KernelExit(ERROR); printf(msg); }
void writeBridgeToPipe() { int rc = PipeWrite(pipe_id, (void *) b, sizeof(Bridge)); if (rc != sizeof(Bridge)) { TracePrintf(TRACE_LEVEL_TERMINAL_PROBLEM, "FAILED TO WRITE BRIDGE\n"); Exit(-1); } }
void DoSpoon(UserContext *context) { // Get an available process id. int newPid = pidCount++; PCB *child = (PCB *)malloc(sizeof(PCB)); // If for any reason we can't fork, return ERROR to calling process. if (!newPid || !child) { context->regs[0] = ERROR; return; } PCB_Init(child); child->id = newPid; child->parent = current_process; queuePush(child->parent->children, child); if (queueIsEmpty(child->parent->children)) TracePrintf(3, "DoSpoon: parent queue empty.\n"); child->status = RUNNING; // Return 0 to child and arm the child for execution. child->user_context = *context; queuePush(ready_queue, child); queuePush(process_queue, child); KernelContextSwitch(SpoonKernel, current_process, child); // Return child's pid to parent and resume execution of the parent. if (current_process->id == newPid) { *context = current_process->user_context; context->regs[0] = 0; } else { context->regs[0] = newPid; } }
int main(int argc, char *argv[]) { while (1) { TracePrintf(1, "Do Init Prog!\n"); Pause(); } return 0; }
void DoExit(UserContext *context) { if (1 == current_process->id) { TracePrintf(1, "Do Exit: init program exiting. Now calling halt.\n"); Halt(); } if (current_process->parent) { current_process->status = context->regs[0]; } TracePrintf(2, "DoExit\n"); KillProc(current_process); TracePrintf(2, "DoExit: Finished the murder\n"); LoadNextProc(context, BLOCK); }