Project 3 Improved Process Management

Similar documents
Introduction. This project will focus primarily on processes.

1 Programs and Processes

Processes and Threads

Project 1 System Calls

Processes & Threads. Today. Next Time. ! Process concept! Process model! Implementing processes! Multiprocessing once again. ! More of the same J

Building Concurrency Primitives

Operating Systems, Assignment 2 Threads and Synchronization

3. Process Management in xv6

Operating Systems Synchronization and Signals

Processes. Today. Next Time. ! Process concept! Process model! Implementing processes! Multiprocessing once again. ! Scheduling processes

The Process Abstraction. CMPU 334 Operating Systems Jason Waterman

Introduction to Operating Systems Prof. Chester Rebeiro Department of Computer Science and Engineering Indian Institute of Technology, Madras

Getting to know you. Anatomy of a Process. Processes. Of Programs and Processes

Processes (Intro) Yannis Smaragdakis, U. Athens

CS 326: Operating Systems. Process Execution. Lecture 5

Pebbles Kernel Specification September 26, 2004

1. Overview This project will help you understand address spaces and virtual memory management.

Project No. 2: Process Scheduling in Linux Submission due: April 12, 2013, 11:59pm

4. The Abstraction: The Process

Reading Assignment 4. n Chapter 4 Threads, due 2/7. 1/31/13 CSE325 - Processes 1

OS lpr. www. nfsd gcc emacs ls 1/27/09. Process Management. CS 537 Lecture 3: Processes. Example OS in operation. Why Processes? Simplicity + Speed

FINE-GRAINED SYNCHRONIZATION. Operating Systems Engineering. Sleep & Wakeup [chapter #5] 15-Jun-14. in the previous lecture.

Chap 4, 5: Process. Dongkun Shin, SKKU

2 Processes. 2 Processes. 2 Processes. 2.1 The Process Model. 2.1 The Process Model PROCESSES OPERATING SYSTEMS

CS3210: Isolation Mechanisms

CIS233J Java Programming II. Threads

LAB 2: PROCESS SYNCHRONIZATION IN XV6

Processes. q Process concept q Process model and implementation q Multiprocessing once again q Next Time: Scheduling

Concurrency, Thread. Dongkun Shin, SKKU

Processes and Threads. Processes and Threads. Processes (2) Processes (1)

by Marina Cholakyan, Hyduke Noshadi, Sepehr Sahba and Young Cha

OPERATING SYSTEMS ASSIGNMENT 3 MEMORY MANAGEMENT

Processes. Chester Rebeiro IIT Madras

Chapter 3 Processes. Process Concept. Process Concept. Process Concept (Cont.) Process Concept (Cont.) Process Concept (Cont.)

CS 31: Intro to Systems Processes. Kevin Webb Swarthmore College March 31, 2016

Operating System Design

Process Concepts. CSC400 - Operating Systems. 3. Process Concepts. J. Sumey

Introduction. Xv6 memory

Changes made in this version not seen in first lecture:

PROCESS MANAGEMENT. Operating Systems 2015 Spring by Euiseong Seo

Chapter 3: Process Concept

Chapter 3: Process Concept

www nfsd emacs lpr Process Management CS 537 Lecture 4: Processes Example OS in operation Why Processes? Simplicity + Speed

PROCESS CONTROL BLOCK TWO-STATE MODEL (CONT D)

Process Time. Steven M. Bellovin January 25,

The UtePC/Yalnix Memory System

MASSACHUSETTS INSTITUTE OF TECHNOLOGY Computer Systems Engineering: Spring Quiz I Solutions

CSE 153 Design of Operating Systems Fall 2018

CS 470 Operating Systems Spring 2013 Shell Project

CS333 Project 1 Test Report Your Name Here

Chapter 3: Process Concept

Windows architecture. user. mode. Env. subsystems. Executive. Device drivers Kernel. kernel. mode HAL. Hardware. Process B. Process C.

Processes. CS3026 Operating Systems Lecture 05

Chapter 3: Processes. Operating System Concepts 8 th Edition,

Lecture Topics. Announcements. Today: Threads (Stallings, chapter , 4.6) Next: Concurrency (Stallings, chapter , 5.

Problem Set: Processes

Operating Systems. Lecture 05

Problem Set: xv6. Lecture Notes on Operating Systems. 1. Consider the following lines of code in a program running on xv6.

CS355 Hw 4. Interface. Due by the end of day Tuesday, March 20.

Project 2 Overview: Part A: User space memory allocation

CS61 Scribe Notes Date: Topic: Fork, Advanced Virtual Memory. Scribes: Mitchel Cole Emily Lawton Jefferson Lee Wentao Xu

Linux Operating System

OS lpr. www. nfsd gcc emacs ls 9/18/11. Process Management. CS 537 Lecture 4: Processes. The Process. Why Processes? Simplicity + Speed

Chapter 3: Processes. Operating System Concepts 9 th Edit9on

Unix Processes. What is a Process?

CS Operating Systems

CS Operating Systems

Problem Set: Processes

Processes. Today. Next Time. Process concept Process model Implementing processes Multiprocessing once again. Scheduling processes

W4118 Operating Systems. Junfeng Yang

REVIEW OF COMMONLY USED DATA STRUCTURES IN OS

Cool Container Crew 2. BACKGROUND

Project 2: Signals. Consult the submit server for deadline date and time

CPSC 341 OS & Networks. Processes. Dr. Yingwu Zhu

OPERATING SYSTEMS ASSIGNMENT 2 SIGNALS, USER LEVEL THREADS AND SYNCHRONIZATION

Problem Set 2. CS347: Operating Systems

Process Description and Control

Processes. CS 416: Operating Systems Design, Spring 2011 Department of Computer Science Rutgers University

Processes. Process Concept

Killing Zombies, Working, Sleeping, and Spawning Children

CS 537 Lecture 2 - Processes

CPS221 Lecture: Threads

THE PROCESS ABSTRACTION. CS124 Operating Systems Winter , Lecture 7

CS3331 Concurrent Computing Exam 1 Solutions Fall 2018

Phase One: Process and Semaphore Queue Modules

CS3210: Coordination. Tim Andersen

Kernel Support for Paravirtualized Guest OS

Computer Science 322 Operating Systems Mount Holyoke College Spring Topic Notes: Processes and Threads

csci3411: Operating Systems

CHAPTER 3 - PROCESS CONCEPT

Agenda Process Concept Process Scheduling Operations on Processes Interprocess Communication 3.2

Process a program in execution; process execution must progress in sequential fashion. Operating Systems

Introduction to Operating System

Chapter 3: Processes

CMSC421: Principles of Operating Systems

This is an open book, open notes exam. But no online or in-class chatting.

The course that gives CMU its Zip! Concurrency I: Threads April 10, 2001

PROCESS CONTROL: PROCESS CREATION: UNIT-VI PROCESS CONTROL III-II R

CS 370 Operating Systems

There are 10 total numbered pages, 5 Questions. You have 60 minutes. Budget your time carefully!

Transcription:

Project 3 Improved Process Management

Introduction This project will modernize process management in xv6. All process management will be impacted. New console control sequences will be implemented to support testing and debugging of the new process management facility. Increasing the efficiency of process management will be the principle focus of this project. The current mechanisms are inefficient in that they traverse a single array (ptable.proc[]) that contains all processes, regardless of state. In this project, you will: 1. Implement a new approach to process management with improved efficiency. The new approach will encompass (a) Process scheduling (b) Process allocation and deallocation. (c) Transactional semantics for all process state transitions 1. 2. Expand the console debug facility with new control sequences. 3. Learn to implement complex concurrency control in the xv6 kernel. This project will use a new Makefile flag, -DCS333 P3P4, for conditional compilation. The same flag will be used in project 4. New Lists You will add ready, free, sleep, zombie, running, and embryo lists to the current approach. Each list corresponds to a state of the xv6 state transition model. Adding these lists to xv6 will not require that you abandon the current array of processes that is created at boot time, but you will hide its use. Instead, you will create a new structure struct StateLists to store these lists, add a field of that structure to struct ptable, and add a new field to the struct proc in proc.h that points to the next process for whatever list a process is a member. You will have six new pointers in struct StateLists: ready, free, sleep, zombie, running, and embryo to point to the first process, or head, of each list, or NULL if the list is empty. You will use these pointers to more efficiently traverse the existing process array when looking for processes in each of the six possible states. You must take into account new concurrency requirements when handling these new lists. Once implemented, every process will be on one of these six lists. Moreover, except as noted below, the code in proc.c will no longer reference the ptable.proc[] array. The current process table, ptable, is defined at the beginning of proc.c: struct { struct s p i n l o c k l o c k ; struct proc proc [NPROC] ; } ptable ; You will add this new structure just above the ptable definition: struct S t a t e L i s t s { struct proc ready ; struct proc f r e e ; struct proc s l e e p ; struct proc zombie ; struct proc running ; struct proc embryo ; } ; and then change the ptable structure to: 1 We define transactional semantics to be that a transaction executes atomically with respect to other code. The failure of such a transaction will leave the relevant part of the system in the same state as before the transaction. 1

struct { struct s p i n l o c k l o c k ; struct proc proc [NPROC] ; struct S t a t e L i s t s p L i s t s ; } ptable ; and change the definition of struct proc in proc.h to have a pointer, called next, to the next item in each list. Each list corresponds to a state of the xv6 state transition model as discussed in class. Invariants All processes on the ready list are in the RUNNABLE state; able to be scheduled on a processor. All processes on the free list are in the UNUSED state; able to be allocated to a new process. All processes on the sleep list are in the SLEEPING state; waiting on some future event. All processes on the zombie list are in the ZOMBIE state; waiting to be reaped by their parent process or the init process. All processes on the running list are in the RUNNING state; executing on a CPU 2. All processes on the embryo list are in the EMBRYO state; being initialized. A process must be on one, and only one, list at a time. The guarantee that a processes exist only on a specific list at a specific time, reflecting its current state, is an invariant, or property that remains unchanged during execution 3. The reality is that there will be times when a process will not be on a list when it transitions from one state to the next. This in between time must be carefully hidden from all threads of control except the one manipulating the process by using transactional semantics. Be very careful to not violate invariants when manipulating processes; you risk introducing errors that can lead to a panic, system hang, or corrupted state within xv6. As a precaution, your code for removing an item from one of the lists is required to check to ensure that the process removed is actually in the correct state (i.e., not put there in error) and panic with an appropriate error message if the check fails. E.g., a process being removed from the running list must be checked to ensure that its state at the time of removal is RUNNING. Initializing the Lists The first xv6 process is created in the routine userinit() in the file proc.c. This is where you will need to initialize the lists. You should initialize the free list when you first enter this routine. This is because the routine will then call allocproc() which is where a process will be removed from the free list and allocated. allocproc() will place the process into the EMBRYO state. At the very end of userinit() you will have a RUNNABLE process. The process needs to be put on the ready list. Since you know that it is the very first process, you can just have ptable.plists.ready point to this process. Do not forget to set the next pointer of the process to 0 (NULL). Be sure to initialize the remaining lists to be empty. While the list pointers will already be set to zero, doing so here makes the requirement that these lists are empty explicit without impacting performance. List Management The act of removing a process from a list and moving it to another list is a manifestation of a state transition. All code for managing state transitions is in the file proc.c. It is important that you understand list invariants and concurrency before making these changes to xv6. Be particularly careful to handle the cases where a state transition fails; you will need to ensure that the process goes back to the list that it was removed from in order to maintain the invariant. There are several locations in proc.c where a state transition can fail; you will need to update this processing to the new approach. Not all state transitions are listed here; there are others that you will need to locate and change as appropriate. For the scheduler, you will use the stub scheduler() routine that already exists in proc.c and is activated with the new compiler flag. Start by copying the existing scheduler to the new routine and then modifying the code to correctly use the new ready list. This is where a process will transition from the RUNNABLE state to the RUNNING state. You will also need list management where the state for a process transitions to the RUNNABLE state. Be sure 2 The maximum number of elements in this list is NCPU, the number of CPUs in xv6 (see param.h) 3 For our purposes, the definition of invariant is a quantity or expression that is constant throughout a certain range of conditions. (from dictionary.com) 2

to add the scheduled process to the running list when its state transitions accordingly in the new scheduler(), and remove it from this list in the appropriate routine when it is about to yield the CPU. Note that the transition from the RUNNING state can put the process into one of three different states: RUNNABLE, SLEEPING, or ZOMBIE. You will modify the allocproc() routine to use the free list when searching for a process in the UNUSED state. You will also need to manage the free list where the state for a process transitions to the UNUSED state. Be sure to add the process to the embryo list in the routine allocproc(). The process will transition from the EMBRYO to RUNNABLE state in the userinit() and fork() routines. Use the stub wakeup1() routine, that already exists in proc.c and is activated with the new compiler flag, to improve the existing wakeup1() routine using the sleep list be careful, more than one process can be woken here! Start by copying the existing wakeup1() routine to the new routine, and then modifying the code to correctly use the new sleep list. You will also need to manage the sleep list where the state for a process transitions to the SLEEPING state. Similarly, modify the stub exit(), kill(), and wait() routines to use the ready, sleep, zombie, embryo, and running lists to remove traversals of the ptable.proc[] structure while having the same functionality as the existing code. Carefully copy the existing exit(), wait() and kill() routines to their stub routines and modify the code to correctly use the new lists. Keep in mind that all code for managing processes is in the file proc.c. In the current kernel, any time that the state of a process is checked or changed, one of the values from enum procstate in proc.h will be used. This is a very good use of the C enumerator type. It should be clear that these lists will improve certain performance aspects of xv6. If this isn t clear to you, be sure to ask as it is rather important. List Manipulation You will need basic knowledge of linked list manipulation (CS 163) to successfully complete this project. Think very carefully about how you will be inserting into/removing from each list. You will partly be graded on the efficiency of your code. Course staff suggest using a single-linked list. There are more efficient lists, but the focus here is not on the list structure but the state transitions. A more complex approach will not earn additional points. A Note on Complexity Since all processes on the free list are equivalent and any one can be used to satisfy an allocation request, efficient management of this list will be different from the other lists. Free list insertion and removal can be managed with a complexity of O(1) rather than O(n). Insertion into the sleep, zombie, running and embryo lists can also be accomplished in O(1) time. Other routines will remain O(n) but the size of n will be substantially reduced. Hints/Suggestions Course staff recommend that you implement the free, ready, and sleeping lists first. Creating helper functions will likely aid greatly in the organization of your code. Code for state transitions not yet converted to use the new lists can continue to use the ptable.proc[] structure without issue, unless there is a dependency be careful!. You will find that much of your list manipulation will be similar for most of the lists. Course staff recommend that you abstract common functionality to helper functions. The slight increase in calling complexity is more than offset by having list manipulation functions in fewer functions; avoid copy-and-paste whenever possible. For example, you can write the following, generic method static int removefromstatelist ( struct proc s L i s t, struct proc p ) to remove p from the state list slist, where *slist would denote the head. To remove a process p from the running list using this method, write int rc = removefromstatelist(& p table. p L i s t s. running, p ) ; where rc is the return code that indicates success or failure. Similarly, you might find that you are also writing the same code when checking the state of removed process and possibly panic the kernel. This is where the enum representation of process states come in handy. You can write a separate method static void a s s e r t S t a t e ( struct proc p, enum p r o c s t a t e s t a t e ) 3

that asserts p->state is state and panics the kernel if the assertion is false (be sure to provide a useful message in your call to panic). The states[] array can then be used to print out the name of the required process state in the panic message. For example if you want to check that a removed process p is in the RUNNABLE state, you can call a s s e r t S t a t e (p, RUNNABLE) ; A suitable abstraction will help to make your code easier to maintain and less prone to errors. Other useful abstractions include static int addtostatelistend ( struct proc s L i s t, struct proc p ) ; static int addtostatelisthead ( struct proc s L i s t, struct proc p ) ; Conditional Compilation In this project, you are required to implement alternate versions of entire functions in proc.c. The reason for this approach is that if you are having trouble with a specific function, you can go back to the old version of that one routine just by changing the conditional compilation flag enclosing that one routine. For the next project, it isn t critical that all lists use this new approach, so it will be possible to turn off certain lists that are not working correctly and not delay work on the next assignment. Speak with the course staff if you find yourself needing to turn off certain functionality as there are dependencies. Scheduler xv6 already uses a round-robin scheduler. It isn t obvious, but if you pay careful attention to how each CPU is initialized, you can readily see that the routine scheduler() implements a round-robin algorithm, albeit inefficiently. You will be improving the efficiency of the scheduler, not implementing a new algorithm. The round-robin scheduling algorithm is conceptually simple. 1. If there is a process at the head of the ready list (a) Remove it (b) Give it the CPU 2. When a process yields the CPU (a) Determine next state/list (b) If the new list is the ready list, place the process at the back of the list; otherwise place it anywhere on the new list (c) Invoke the scheduler via sched() Since xv6 now uses state lists, the new scheduler() implementation will more closely match our high-level description of the round-robin algorithm. Note that the scheduler() routine does not perform step 2. New Console Control Sequences You will add new console control sequences control r, control f, control s and control z that will print information about the ready, free, sleep, and zombie lists, respectively. Detection of control sequences occurs in the routine consoleintr() in console.c. Observe how control p is handled you will do something similar for control r, control f, control s, and control z. 4

control r This control sequence will print the PIDs of all the processes that are currently on the ready list. Your output should look something like below: Ready List Processes: 1 2 3... n where 1 is the PID of the first process in the ready list (the head), and n is the PID of last process in the list (the tail). control f This control sequence will print the number of processes that are on the free list. Your output will be Free List Size: N processes where N is the number of elements in the free list. control s This control sequence will print the PIDs of all the processes that are currently on the sleep list. Its format will be similar to control r above, except that you will title it as Sleep List Processes instead of Ready List Processes. control z This control sequence will print the PIDs of all the processes that are currently on the zombie list as well as their parent PID. Its format will be similar to control r above: Zombie List Processes: (PID1, PPID1) (PID2, PPID2) (PID3, PPID3)... (PIDn, PPIDn) where PID1 is the PID of the first process on the list (the head) and PPID1 is the PID of the parent of process 1. The PID of the last process on the list (the tail) is PIDn and PPIDn is the PID of parent process of process n. Required Tests Your tests must, at a minimum, 1. Demonstrate that the free list is correctly initialized when xv6 is booted. Note that init and sh should be the only two active processes immediately after boot while the rest are unused. Recall that the NPROC variable represents the maximum number of processes in xv6. 2. Demonstrate that the free list is correctly updated when a new process is allocated (state transitions from UNUSED) and when a process is deallocated (state transitions to UNUSED). 3. Demonstrate the kill shell command causes a process to correctly transition to the ZOMBIE and then UNUSED states. 4. Demonstrate that round-robin scheduling is enforced. Specifically, the processes that are already in the ready list are scheduled before processes added afterwards; any process transitioning to the RUNNING state are removed from the front of the ready list. Processes transitioning to the RUNNABLE state must be added at the back of the ready list. 5. Demonstrate that the sleep list is correctly updated when a process sleeps (state transitions to SLEEPING) and when processes are woken (state transitions from SLEEPING). 6. Demonstrate that the zombie list is correctly updated when a process exits (state transitions to ZOMBIE) and when a process is reaped (state transitions from ZOMBIE). 7. Demonstrate that output for the console commands control r, control f, control s and control z is correct. 5

Discussion Some of the features optimized in this project depend on each other to function correctly. One example is process deallocation and reaping zombie processes. In xv6, a process is deallocated after it has been reaped when in the ZOMBIE state. For this project, it means that the process is managed by the zombie list before it is managed by the free list. Hence, the zombie list must work correctly for the free list to be correct. This means you can test that Requirements 1, 2 and 6 are met using a single test command. One possible approach in the implementation of this command, call it zombiefree for the sake of discussion, is as follows: 1. Fork a child process until fork() fails, storing each child s PID and the total number of children created. 2. When fork() fails, print out the total number of children created and then put the parent process to sleep for a few seconds. 3. After waking up from sleep, use the stored child PIDs to kill off all of the children using the kill() system call. Only call kill() for the n th child after the n 1 th child has been deallocated you can check this by looping on the wait() system call until it returns the correct PID, instead of 1. 4. After all of the children have been killed off, exit the test program. You are not required to use zombiefree to test Requirements 1, 2 and 6. The command and above discussion are only intended to facilitate your thinking in writing the necessary tests. If you do want to use zombiefree, however, think about how you can use control f and control z to give you the information you need. Also note that it is possible to use zombiefree to meet additional requirements. Finally, if you have a correct implementation of the elapsed CPU time functionality in Project 2, you can write a simple test that will verify the correctness of Requirement 3 using control p and several infinitely looping processes. Voilà If you now look through the code in proc.c you will notice that there are only three locations where the ptable.proc[] structure is used: 1) userinit(); 2) procdump(); and 3) getprocs(), although you can update getprocs() if you so desire. All other references to the array have been removed. You have now isolated (or hidden) how processes are stored from how they are used. Adding this level of abstraction/indirection is very powerful as it allows a wide variety of approaches for handling storage for processes, even dynamic creation and destruction! Congratulations, you just made process management for xv6 much more like operating systems such as Linux. 6