+--------------------+ | OS Development | | PROJECT 0: INTRO | | DESIGN DOCUMENT | +--------------------+ ---- GROUP ---- >> Fill in the names and email addresses of your group members. Peter Ketscher Karoline Knoth Manuel Mausz ---- PRELIMINARIES ---- >> If you have any preliminary comments on your submission, notes for the >> TAs, or extra credit, please give them here. >> Please cite any offline or online sources you consulted while >> preparing your submission, other than the Pintos documentation, course >> text, lecture notes, and course staff. Stallings, W. - Operating Systems ALARM CLOCK =========== ---- DATA STRUCTURES ---- >> A1: Copy here the declaration of each new or changed `struct' or >> `struct' member, global or static variable, `typedef', or >> enumeration. Identify the purpose of each in 25 words or less. struct thread: int64_t wakeup_tick ...absolute tick when to wake up the thread timer.c: static struct list wakeup_list ...list of processes waiting for an wakeup event and currently put to sleep ---- ALGORITHMS ---- >> A2: Briefly describe what happens in a call to timer_sleep(), >> including the effects of the timer interrupt handler. In case of a positive tick value we calculate the tick when to awake the current thread and store that inside the per thread structure. Afterwards we disable interrupts and insert the thread into our wakup list which is sorted by wakeup-tick in ascending order. Finally we block the thread and restore the interrupt value. >> A3: What steps are taken to minimize the amount of time spent in >> the timer interrupt handler? We sort our alarm/wake-up list by wakeup-tick value in ascending order. Thus we can return as soon as the first thread doesn't need to get unblocked. ---- SYNCHRONIZATION ---- >> A4: How are race conditions avoided when multiple threads call >> timer_sleep() simultaneously? Each thread has its own variable for saving its sleep period therefore no race conditions arise while setting the latter. Furthermore during the access to the static wakup_list, interrupts are disabled to prevent thread preemption. >> A5: How are race conditions avoided when a timer interrupt occurs >> during a call to timer_sleep()? We've disabled the interrupts during list operations. ---- RATIONALE ---- >> A6: Why did you choose this design? In what ways is it superior to >> another design you considered? It's very simple, doesn't require any complex structures and memory allocations and fulfills the needs of project0. ARGUMENT PASSING ================ ---- DATA STRUCTURES ---- >> A1: Copy here the declaration of each new or changed `struct' or >> `struct' member, global or static variable, `typedef', or >> enumeration. Identify the purpose of each in 25 words or less. struct start_aux_data: char *args ...renamed from filename to args as we strip off the executable name early and only store the commandline arguments ---- ALGORITHMS ---- >> A2: Briefly describe how you implemented argument parsing. How do >> you arrange for the elements of argv[] to be in the right order? >> How do you avoid overflowing the stack page? First we strip off the executable name from the command string and pass it to thread_create(). Thus we name threads by their executable. After passing the arguments through start_process(), load() and setup_stack() we first copy the whole arguments byte array following the executable name onto the stack. Afterwards we align the current stack address and proceed with creating the argv[]-pointers by walking through the already copied arguments in reverse order. This way we can replace all space characters with 0-characters and at the same time detect the start of every argument which we push onto the stack. Additional we check for possible stack overflow. The walking order is already the correct order necessary for the argv[]-pointers on the stack. As a last step we push the address of the executable name, the address of the argv[] itself, the number of commandline arguments and a fake return addres onto the stack. Overflowing is avoided calculating the end of the stack and checking the current stack pointer after every push of an argv[]-pointer entry. ---- RATIONALE ---- >> A3: Why does Pintos implement strtok_r() but not strtok()? strtok() uses global data, so it is unsafe in threaded programs such as kernels. >> A4: In Pintos, the kernel separates commands into a executable name >> and arguments. In Unix-like systems, the shell does this >> separation. Identify at least two advantages of the Unix approach. * Possible bugs in the code will either just break the shell or allow code execution with user privileges. Otherwise this could lead to a kernel oops or even worse code execution within the kernel. * Outsourcing command separation from the kernel leads to a leaner less complex kernel implementation and reduces the kernel workload because tasks like searching for a command name in file system can be delegated to the shell. SURVEY QUESTIONS ================ Answering these questions is optional, but it will help us improve the course in future quarters. Feel free to tell us anything you want--these questions are just to spur your thoughts. You may also choose to respond anonymously in the course evaluations at the end of the quarter. >> In your opinion, was this assignment, or any one of the three problems >> in it, too easy or too hard? Did it take too long or too little time? >> Did you find that working on a particular part of the assignment gave >> you greater insight into some aspect of OS design? >> Is there some particular fact or hint we should give students in >> future quarters to help them solve the problems? Conversely, did you >> find any of our guidance to be misleading? >> Do you have any suggestions for the TAs to more effectively assist >> students, either for future quarters or the remaining projects? >> Any other comments? It took us about 25 hours to complete this assignment.