Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

OS161 kernel help : The question is asking to thread calling in syscall.c , and use void _eixt(int exitcode) right? I am confused about this.

OS161 kernel help :

image text in transcribed

The question is asking to thread calling in syscall.c , and use void _eixt(int exitcode) right?

I am confused about this. Can anyone please help ?

syscall.c file:

#include #include #include #include #include #include #include #include

/* * System call dispatcher. * * A pointer to the trapframe created during exception entry (in * exception-*.S) is passed in. * * The calling conventions for syscalls are as follows: Like ordinary * function calls, the first 4 32-bit arguments are passed in the 4 * argument registers a0-a3. 64-bit arguments are passed in *aligned* * pairs of registers, that is, either a0/a1 or a2/a3. This means that * if the first argument is 32-bit and the second is 64-bit, a1 is * unused. * * This much is the same as the calling conventions for ordinary * function calls. In addition, the system call number is passed in * the v0 register. * * On successful return, the return value is passed back in the v0 * register, or v0 and v1 if 64-bit. This is also like an ordinary * function call, and additionally the a3 register is also set to 0 to * indicate success. * * On an error return, the error code is passed back in the v0 * register, and the a3 register is set to 1 to indicate failure. * (Userlevel code takes care of storing the error code in errno and * returning the value -1 from the actual userlevel syscall function. * See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.) * * Upon syscall return the program counter stored in the trapframe * must be incremented by one instruction; otherwise the exception * return code will restart the "syscall" instruction and the system * call will repeat forever. * * If you run out of registers (which happens quickly with 64-bit * values) further arguments must be fetched from the user-level * stack, starting at sp+16 to skip over the slots for the * registerized values, with copyin(). */ void syscall(struct trapframe *tf) { int callno; int32_t retval; int err;

KASSERT(curthread != NULL); KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_iplhigh_count == 0);

callno = tf->tf_v0;

/* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */

retval = 0;

switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break;

case SYS___time: err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1); break;

/* Add stuff here */

default: kprintf("Unknown syscall %d ", callno); err = ENOSYS; break; }

if (err) { /* * Return the error code. This gets converted at * userlevel to a return value of -1 and the error * code in errno. */ tf->tf_v0 = err; tf->tf_a3 = 1; /* signal an error */ } else { /* Success. */ tf->tf_v0 = retval; tf->tf_a3 = 0; /* signal no error */ }

/* * Now, advance the program counter, to avoid restarting * the syscall over and over again. */

tf->tf_epc += 4;

/* Make sure the syscall code didn't forget to lower spl */ KASSERT(curthread->t_curspl == 0); /* ...or leak any spinlocks */ KASSERT(curthread->t_iplhigh_count == 0); }

/* * Enter user mode for a newly forked process. * * This function is provided as a reminder. You need to write * both it and the code that calls it. * * Thus, you can trash it and do things another way if you prefer. */ void enter_forked_process(struct trapframe *tf) { (void)tf; }

crt0.s file :

#include

#include

.set noreorder /* so we can use delay slots explicitly */

.text .globl __start .type __start,@function .ent __start __start: /* Load the "global pointer" register */ la gp, _gp

/* * We expect that the kernel passes argc in a0, argv in a1, * and environ in a2. We do not expect the kernel to set up a * complete stack frame, however. * * The MIPS ABI decrees that every caller will leave 16 bytes of * space in the bottom of its stack frame for writing back the * values of a0-a3, even when calling functions that take fewer * than four arguments. It also requires the stack to be aligned * to an 8-byte boundary. (This is because of 64-bit MIPS, which * we're not dealing with... but we'll conform to the standard.) */ li t0, 0xfffffff8 /* mask for stack alignment */ and sp, sp, t0 /* align the stack */ addiu sp, sp, -16 /* create our frame */

sw a1, __argv /* save second arg (argv) in __argv for use later */ sw a2, __environ /* save third arg (environ) for use later */

jal main /* call main */ nop /* delay slot */

/* * Now, we have the return value of main in v0. * * Move it to s0 (which is callee-save) so we still have * it in case exit() returns. * * Also move it to a0 so it's the argument to exit. */ move s0, v0 /* save return value */ 1: jal exit /* call exit() */ move a0, s0 /* Set argument (in delay slot) */

/* * exit() does not return. (Even if _exit() is not implemented * so *it* returns, exit() is supposed to take care of that.) * But just in case, loop and try again. */ b 1b /* loop back */ nop /* delay slot */ .end __start

Syscall: void exit(int exitcode) All user programs end by calling the_exit system call, even if your main) function does not end with the C library exit) function. Ever wonder what calls main in the first place or where it goes when it returns? Have a look at userland/lib/crt0/mips/crto.S-this is where your user-level C programs really start executing. You should be able to find the call to main) and the call to_exit after main returns. Without an implementation of_exit, the threads created to handle user programs just hang around forever, executing an infinite loop in user space and taking up a lot of the CPU time. You should be able to locate that loop in mips/crtO.S as well. Handle_exit so that the thread calling_exit is fully destroyed and all memory is returned to the system. You should be able to implement this system call with a few lines of code in syscall.c HINT: Find an existing function that is an ideal handler for the exit system call. Modify this function to receive the exit code parameter. You will also have to modify all other uses of this function to pass an exit code. You should pass an appropriate exit code to this function, based on the exit value supplied by the user-level process, using the macros supplied in kern/include/kern/wait.h. Use a DEBUGO statement in this function to print out the exit code if the DB SYSCALL messages are enabled. The exit code would ordinarily need to be stored in some data structure associated with the thread, so that another thread could check its exit status However, it turns out that cleaning up threads is a complex process, so for this assignment you don't need to store the exit code anywhere

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions