Process Sheduling Lab

Similar documents
Term Project Phase II: The Scheduler Ter m Proj ect Phas e II:

Chapter 6: CPU Scheduling

Processes. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

Killing Zombies, Working, Sleeping, and Spawning Children

CS370 Operating Systems

Chapter 6: CPU Scheduling

Lecture 2 Process Management

CS370 Operating Systems

Processes. Overview. Processes. Process Creation. Process Creation fork() Processes. CPU scheduling. Pål Halvorsen 21/9-2005

CSC Operating Systems Spring Lecture - XII Midterm Review. Tevfik Ko!ar. Louisiana State University. March 4 th, 2008.

CS24: INTRODUCTION TO COMPUTING SYSTEMS. Spring 2018 Lecture 20

Chapter 5: CPU Scheduling

CSE 451: Operating Systems Winter Module 4 Processes. Mark Zbikowski Allen Center 476

Processes. CS 475, Spring 2018 Concurrent & Distributed Systems

Chapter 5: CPU Scheduling. Operating System Concepts Essentials 8 th Edition

Chapter 6: CPU Scheduling. Operating System Concepts 9 th Edition

SMD149 - Operating Systems

INF1060: Introduction to Operating Systems and Data Communication. Pål Halvorsen. Wednesday, September 29, 2010

Scheduling. Scheduling 1/51

CHAPTER 2: PROCESS MANAGEMENT

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

Lecture 17: Threads and Scheduling. Thursday, 05 Nov 2009

Creating a Shell or Command Interperter Program CSCI411 Lab

PROCESSES. Jo, Heeseung

Processes. Jo, Heeseung

Operating System Structure

Problem Set: Processes

CSE 410: Computer Systems Spring Processes. John Zahorjan Allen Center 534

Processes. Operating System CS 217. Supports virtual machines. Provides services: User Process. User Process. OS Kernel. Hardware

Scheduling. Scheduling 1/51

Process management. What s in a process? What is a process? The OS s process namespace. A process s address space (idealized)

Processes, Context Switching, and Scheduling. Kevin Webb Swarthmore College January 30, 2018

Signals, Synchronization. CSCI 3753 Operating Systems Spring 2005 Prof. Rick Han

CPU Scheduling. Daniel Mosse. (Most slides are from Sherif Khattab and Silberschatz, Galvin and Gagne 2013)

Processes, PCB, Context Switch

Computer Systems II. First Two Major Computer System Evolution Steps

CPU Scheduling Algorithms

Problem Set: Processes

PROCESS MANAGEMENT. Operating Systems 2015 Spring by Euiseong Seo

Operating Systems. Figure: Process States. 1 P a g e

CPU Scheduling. Basic Concepts. Histogram of CPU-burst Times. Dispatcher. CPU Scheduler. Alternating Sequence of CPU and I/O Bursts

(MCQZ-CS604 Operating Systems)

Class average is Undergraduates are performing better. Working with low-level microcontroller timers

Unix Processes. What is a Process?

Processes and Threads

PROCESS CONTROL BLOCK TWO-STATE MODEL (CONT D)

Properties of Processes

Chapter 5 CPU scheduling

PROGRAMMING PROJECT ONE DEVELOPING A SHELL

Chapter 5: CPU Scheduling. Operating System Concepts 9 th Edit9on

CSCE 313 Introduction to Computer Systems. Instructor: Dezhen Song

CSCE 313: Intro to Computer Systems

Ch 4 : CPU scheduling

Chapter 5: CPU Scheduling

Chap 4, 5: Process. Dongkun Shin, SKKU

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

OPERATING SYSTEMS. UNIT II Sections A, B & D. An operating system executes a variety of programs:

High level scheduling: Medium level scheduling: Low level scheduling. Scheduling 0 : Levels

Mon Sep 17, 2007 Lecture 3: Process Management

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

Chapter 5: CPU Scheduling

Processes & Signals. System Runs Many Processes Concurrently. State consists of memory image + register values + program counter

Computer Systems Assignment 2: Fork and Threads Package

* What are the different states for a task in an OS?

SE350: Operating Systems

Chapter 6: CPU Scheduling. Operating System Concepts 9 th Edition

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

Processes. What s s a process? process? A dynamically executing instance of a program. David Morgan

Unit 3 : Process Management

5/8/2012. Controlling User Processes Chapter 10

Chapter 3: Process Concept

OPERATING SYSTEMS CS3502 Spring Processor Scheduling. Chapter 5

CS370 Operating Systems

Process- Concept &Process Scheduling OPERATING SYSTEMS

Multitasking. Programmer s model of multitasking. fork() spawns new process. exit() terminates own process

CS 326: Operating Systems. Process Execution. Lecture 5

Signals. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

Linux Kernel PROCESS. Copyrighted to

Processes in linux. What s s a process? process? A dynamically executing instance of a program. David Morgan. David Morgan

Processes Prof. James L. Frankel Harvard University. Version of 6:16 PM 10-Feb-2017 Copyright 2017, 2015 James L. Frankel. All rights reserved.

CS 4410, Fall 2017 Project 1: My First Shell Assigned: August 27, 2017 Due: Monday, September 11:59PM

Comparison of soft real-time CPU scheduling in Linux kernel 2.6 series with Solaris 10

CS3733: Operating Systems

Operating Systems. Lecture 05

Programming Assignments will be.. All the PAs are continuous 3 major factors that you should consider

Announcement. Exercise #2 will be out today. Due date is next Monday

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

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

OPERATING SYSTEMS. COMS W1001 Introduction to Information Science. Boyi Xie

Operating Systems and Networks Assignment 2

Chapter 5 Process Scheduling

Chapter 5: Process Scheduling

Lecture Topics. Announcements. Today: Uniprocessor Scheduling (Stallings, chapter ) Next: Advanced Scheduling (Stallings, chapter

518 Lecture Notes Week 3

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

Chapter 5: CPU Scheduling. Operating System Concepts 8 th Edition,

Project 2: CPU Scheduling Simulator

CS307: Operating Systems

Signals: Management and Implementation. Sanjiv K. Bhatia Univ. of Missouri St. Louis

CS 213, Fall 2002 Lab Assignment L5: Writing Your Own Unix Shell Assigned: Oct. 24, Due: Thu., Oct. 31, 11:59PM

Transcription:

Process Sheduling Lab CSCI411 Lab Inspired by Operating System Concepts, 8 th Edition, Silberschatz, Galvin, Gagne Adapted by M.D Doman 2013 Exercise Goal: You will learn more about how process management is designed, particularly how the scheduler is implemented. The scheduler is the heart of the multiprogramming system; it is responsible for choosing a new task to run whenever the CPU is available.you will learn how implement both a First-Come-First-Served process dispatcher, and, effectively, a Round-Robin dispatcher. Contents Introduction... 2 Problem Statement... 4 Problem Statement 1: First-Come-First Serve Process Dispatcher... 4 Problem Statement 1: RoundRobin Dispatcher... 5 Attacking the Problem... 5 First-Come-First Serve Process Dispatcher... 5 RoundRobin Dispatcher... 7 Process to be dispatched:... 7 fork() and exec() calls from shell program... 8 I/O Redirection... 9 Submission Requirements... 10 Appendix: Feedack Dispatcher... 11 Appendix: Fair-Share Scheduling Dispatcher... 12

Introduction Process management is the part of the OS that creates and destroys processes, provides mechanism for synchronization and multiplexes the CPU among runnable processes. This exercised considers the last part, focusing on the scheduler. Linux uses a different low-level view of how the OS is designed than the process model that appears at the system call interface. In this low-level view, when the hardware is started a single hardware process begins to run. After the Linux kernel has been loaded, the initial process is created (to use up all otherwise unused CPU cycles) and then Linux processes are started according to how the machine is configured to operate. For example, getty ( get teletype ) processes are started for each login port and daemons are started as specified. Thus, when the system is ready for normal operation, several processes are in existence, most of which are blocked on various conditions. The runnable tasks (those whose states are TASK_RUNNING) begin competing for the CPU. A fork() command defines a new kernel process. The initial process simply multiplexes among the programs that are loaded in different address spaces as it sees fit (and as defined by the task descriptor). That is, within the kernel, only one thread of execution exists that jumps from one runnable task to another. At the system call interface, this behavior has the appropriate UNIX process semantics. Process States The state field in the task descriptor can have any of the following values: TASK_RUNNING TASK_I NTERRU PTI BLE TASK_UNINTERRUPTIBLE TASK_ZOMBIE TASK_STOPPED As you go through the kernel code, you will often see statements of the form current-e-state = TASK_".; For example, in the sleep_on() code, state is set to TASK_UNINTERRUPTIBLE just before the process is placed on a wait queue. In wake_up(), state is set back to TASK_RUNNING after it is removed from the wait queue. Recall that the distinction between the TASK_INTERRUPTIBLE and TASK_UNINTERRUPTIBLE states relates to the sleeping task's ability to accept signals. TASK_ZOMBIE represents a state in which a process has terminated, but its parent has not yet performed a wait() system call to recognize that it has terminated. That is, the task does not disappear from the system until the parent is notified of its termination. The final possible value for the state field is TASK_STOPPED, which means that the task has been halted by a signal or through the ptrace mechanism. Thus most of the kernel code sets the state field to TASK_RUNNING, TASK_INTERRUPTIBLE, or TASK_UNINTERRUPTIBLE. Outside of the kernel, a different set of process states is visible to users. These states are defined by the POSIX rnodel rather than by the Linux implementation, though they are analogous to the internal states kept in the task descriptor. You can review these external states by inspecting the manual page for the STAT column in a ps command. The ps has three fields. ps FIELD 1: The first field may be one of the following: R: The process is running or runnable (its kernel state is TASK_RUNNING).

S: The process is sleeping (its kernel state is TASK_INTERRUPTIBLE). D: The process is in an uninterruptible sleep (its kernel state is TASK_ UNNTERRUPTIBLE). T: The process is either stopped or being traced (its kernel state is TASK_STOPPED). Z: The process is in the zombie state (its kernel state is TASK_ZOMBIE ps FIELD 2: The second field of ps is either blank, or W if the process currently has no pages loaded. The third field is either blank, or N if the process is running at a reduced priority. Most of the kernel code transitions the state of the process among TASK_RUNNING, TASK_INTERRUPTIBLE, and TASK_UNINTER- RUPTIBLE. Roughly speaking, whenever a process is to be blocked, it will be put on a queue (usually a wait queue) and its state will be changed to one of TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE and then the scheduler will be called. A task/process, when awakened, is removed from the wait queue and its state is changed to TASK_RUNNING. This leaves the scheduler as the final critical piece of process management that this manual considers. Scheduler Implementation The scheduler is a kernel function, schedule(), that gets called from various other system call functions (usually via sleep_on() ) and after every system call and slow interrupt. Each time that the scheduler is called, it does the following. 1. Performs various periodic work (such as running device bottom halves). 2. Inspects the set of tasks in the TASK_RUNNING state. 3. Chooses one task to execute according to the scheduling policy. 4. Dispatches the task to run on the CPU until an interrupt occurs. The scheduler contains three built-in scheduling strategies, identified by the constants SCHEDJIFO, SCHED_RR, and SCHED_OTHER. The scheduling policy for each process can be set at runtime by using the sched_setscheduler() system call (defined in kernel/sched.c). The task's current scheduling policy is saved in the policy field. The SCHED_FIFO and SCHED_RR policies are intended to be sensitive to real-time requirements, so they use scheduling priorities in the range [0:99], whereas SCHED_OTHER handles only the zero priority. Each process also has a priority field in its task descriptor. Conceptually, the scheduler has a multilevel queue with 100 levels (corresponding to the priorities from 0 to 99). Whenever a process with a priority that is higher than the currently running process becomes runnable, the lower-priority process is preempted and the higher-priority process begins to run. Of course, in the normal timesharing (SCHED_OTHER) policy, processes do not preempt one another, since they all have a priority of zero. Any task/process that uses the SCHED_FIFO policy must have superuser permission and have a priority of 1 to 99 (that is, it has a higher priority than all SCHED_OTHER tasks). Thus a SCHED_FIFO task that becomes runnable takes priority over every SCHED_OTHER task. The SCHED_FIFO policy does not reschedule on a timer interrupt. Once a SCHE SCHED_FIFO task gets control of the CPU, it will retain control until either it completes, blocks by an I/O call, calls sched_yield(), or until a higher priority task becomes runnable. If it yields or is preempted by another, higher-priority, task, it is placed at the end of the task queue at the same priority level. The SCHED_RR policy has the same general semantics as the SCHED_FIFO policy, except that it uses the timeslicing mechanism to multiplex the CPU among tasks that are in the highest-priority queue. A running SCHED_RR

task that is preempted by a higher-priority task is placed back on the head of its queue so that it will resume when its queue priority is again the highest in the system. The preempted process will then be allowed to complete its time quantum. The SCHED_OTHER policy is the default timesharing policy for Linux. It uses the conventional time-slicing mechanism (rescheduling on each timer interrupt) to put an upper bound on the amount of time that a task can use the CPU continuously if other tasks are waiting to use it. This policy ignores the static priorities used to discriminate among tasks in the other two policies. Instead, a dynamic priority is computed on the basis of the value assigned to the task by the nice() or setpriorty() system call and by the amount of time that a process has been waiting for the CPU to become available. Problem Statement Design a dispatcher that satisfies the criteria defined below. o o The dispatcher will be created as a child process from your shell program. To do this, you will replace the system() function call with fork() and exec() calls. Because the shell will be the session leader it will have control and access to the terminal input. The dispatcher must accept a file with list of the programs to dispatch.for the dispatcher process, redirect the stdin and stdout to files. Problem Statement 1: First-Come-First Serve Process Dispatcher Create a FCFS Dispatcher. This will be a shell program. An input file will associate an arrival time for each program so that execution of the program can not start until at least that time elapses. e.g. <arrival time>,program name, <priority>,<cputime> 0,P1,0,3 1 st Job: Arrival time 0, priority 0 (Real-Time), requiring 3 seconds of CPU time 2,P2,0,6 2 st Job: Arrival time 2, priority 0 (Real-Time), requiring 6 seconds of CPU time 4,P3,0,4 6,P4,0,5 8,P5,0,2 You will need to create a queue of job structures so that you only dequeue a job when the appropriate time has elapsed and there is no longer a current job running. (There is a guarantee that the jobs presented in the input dispatch file will be in chronological order of arrival).

Problem Statement 1: RoundRobin Dispatcher Try this with the following job list with a quantum of 1 sec: <arrival time>,program name, <priority>,<cputime> Round Robin Dispatcher (from Stallings) 0,P1,1,3 1 st Job: Arrival time 0, priority 1, requiring 3 seconds of CPU time 2,P2,1,6 2 st Job: Arrival time 2, priority 1, requiring 6 seconds of CPU time 4,P3,1,4 6,P4,1,5 8,P5,1,2 Attacking the Problem First-Come-First Serve Process Dispatcher The first thing to do is to define a process control block structure or class such as: struct pcb { pid_t pid; // system process ID char * args[maxargs]; // program name and args int arrivaltime; int remainingcputime; struct pcb * next; // links for PCB handlers }; typedef struct pcb PCB; typedef PCB * PcbPtr; This structure/class can be used for all the queues (linked lists) needed for the project (with a few extra elements in the structure). Dispatcher algorithm: The basic First-Come-First-Served (FCFS) dispatcher algorithm can be reduced to the following pseudo-code. Note that the tests may appear to be out of order (shouldn't one be doing the test at 4.i after the sleep rather than before it?). With the current model it makes no difference, but there are reasons for doing it in this order as we shall see when we come to the multiple dispatcher models later on.

1. Initialize dispatcher queue; 2. Fill dispatcher queue from dispatch list file; 3. Start dispatcher timer (dispatcher timer = 0); 4. While there's anything in the queue or there is a currently running process: i. If a process is currently running; a. Decrement process remainingcputime; b. If times up: A. Send SIGINT to the process to terminate it; B. Free up process structure memory ii. If no process currently running && dispatcher queue is not empty && arrivaltime of process at head of queue is <= dispatcher timer: a. Dequeue process and start it (fork & exec) b. Set it as currently running process; iii. sleep for one second; iv. Increment dispatcher timer; v. Go back to 4. 5. Exit. Be sure to include: #include <sys/types.h> and #include <signal.h> There are a number of ways to terminate a job. Since we know its process ID, the easiest way to do this is to send the process a terminating signal using the kill function. The one we need to use here is SIGINT, which is the equivalent of the Ctrl-C keyboard interrupt fielded by the shell. Use waitpid will check the termination of your child process. kill (pid, SIGINT); process_status = PCB_TERMINATED;

RoundRobin Dispatcher To suspend and restart processes as required by the Round Robin dispatcher will require the use of the SIGTSTP and SIGCONT signals as well as SIGINT that we used for the FCFS dispatcher.(see below). To make the Round Robin dispatcher work (RR q=1) the logic should be: 1. Initialize dispatcher queues (input queue and RR queue); 2. Fill input queue from dispatch list file; 3. Start dispatcher timer (dispatcher timer = 0); 4. While there's anything in any of the queues or there is a currently running process: i. Unload any pending processes from the input queue: While (head-of-input-queue.arrival-time <= dispatcher timer) dequeue process from input queue and enqueue on RR queue; ii. If a process is currently running: a. Decrement process remainingcputime; b. If times up: A. Send SIGINT to the process to terminate it; B. Free up process structure memory; c. else if other processes are waiting in RR queue: A. Send SIGTSTP to suspend it; B. Enqueue it back on RR queue; iii. If no process currently running && RR queue is not empty: a. Dequeue process from RR queue b. If already started but suspended, restart it (send SIGCONT to it) else start it (fork & exec) c. Set it as currently running process; iv. sleep for one second; v. Increment dispatcher timer; vi. Go back to 4. 5. Exit. or something like that! Try this with the following job list with a quantum of 1 sec: <arrival time>,program name, <priority>,<cputime> 0,P1,1,3 1 st Job: Arrival time 0, priority 1, requiring 3 seconds of CPU time 2,P2,1,6 2 st Job: Arrival time 2, priority 1, requiring 6 seconds of CPU time 4,P3,1,4 6,P4,1,5 8,P5,1,2 Process to be dispatched: The process to be dispatched can be as simple as the following. In fact, it can be the following. The idea is to have the process sleep for a period to ensure the process will run for an allotted time. The sleep function causes the calling

process to be suspended until either the amount of wall clock time specified by seconds has elapsed, or a signal is caught by the process and the signal handler returns. The return value from sleep is either 0 or the number of unslept seconds if the sleep has been interrupted by a signal interrupt. #include <iostream> #include <stdlib.h> #include <unistd.h> using namespace std; int main (int arg, char *argv[]) { int n = atoi(argv[2]); while (0 < n) { printf("process Executing: %s; PID: %lu\n, argv[1], (unsigned long)getpid()); sleep(1); n--; }// end of while }//end of main fork() and exec() calls from shell program Since we need to control what open files and file descriptors are passed the dispatcher, we need more control over there execution. To do this we need to use the fork and exec system calls. 1. In your Shell program, replace the use of system with fork and exec 2. You will now need to more fully parse the incoming command line so that you can set up the argument array (char *argv[] in the above examples). 3. You will find that while a system function call only returns after the program has finished, the use of fork means that two processes are now running in foreground. In most cases you will not want your shell to ask for the next command until the child process has finished. This can be accomplished using the wait or waitpid functions. e.g. switch (child_pid = fork()) { // error condition case -1: syserrmsg("fork",null); break; // I am the dispatcher (child) process case 0: execvp(args[0], args); syserrmsg("exec failed -",args[0]); exit(127); // I am the shell (parent) process default: if (!dont_wait) waitpid(pid, &status, WUNTRACED); Obviously, in the above example, if you wanted to run the child process 'in background', the flag dont_wait would be set and the shell would not wait for the child process to terminate.

I/O Redirection Your project shell must support I/O-redirection on both stdin and stdout. i.e. the command line: programname arg1 arg2 < inputfile > outputfile will execute the program programname with arguments arg1 and arg2, the stdin FILE stream replaced by inputfile and the stdout FILE stream replaced by outputfile. With output redirection, if the redirection character is > then the outputfile is created if it does not exist and truncated if it does. If the redirection token is >> then outputfile is created if it does not exist and appended to if it does. Note: you can assume that the redirection symbols, <, > & >> will be delimited from other command line arguments by white space - one or more spaces and/or tabs. This condition and the meanings for the redirection symbols outlined above and in the project differ from that for the standard shell. I/O redirection is accomplished in the child process immediately after the fork and before the exec command. At this point, the child has inherited all the file-handles of its parent and still has access to a copy of the parent memory. Thus, it will know if redirection is to be performed, and, if it does change the stdin and/or stdout file streams, this will only affect the child not the parent. The easiest way to do this is to use freopen. freopen opens a specified file on a specified stream, closing the stream first if it is already open. This function is typically used to open a specified file as one of the predefined streams, stdin, stdout, or stderr. Freopen ( filename, type, stdin/stdout/stderr) The type string is the standard open argument: type r or rb w or wb a or ab r+ or r+b or rb+ w+ or w+b or wb+ a+ or a+b or ab+ Description open for reading truncate to 0 length or create for writing append; open for writing at end of file, or create for writing open for reading and writing truncate to 0 length or create for reading and writing open or create for reading and writing at end of file where b as part of type allows the standard I/O system to differentiate between a text file and a binary file. Thus: freopen("inputfile", "r", stdin); would open the file inputfile and use it to replace the standard input stream, stdin.. ***********************************************************************/ switch (child_pid = fork()) { // error condition case -1: syserrmsg("fork",null); break; // I am the dispatcher (child) process case 0: // I/O redirection: stdin */ if (myinfile.txt) {

if (!freopen((myinfile.txt, "r", stdin)) errmsg((myinfile.txt,"can't be open for i/p redirect."); } if (myoutfile.txt) { if (!freopen(myoutfile.txt, sstatus.outmode, stdout)) errmsg(myoutfile.txt,"can't be open for o/p redirect."); } execvp(args[0], args); syserrmsg("exec failed -",args[0]); exit(127); // I am the shell (parent) process default: if (!dont_wait) waitpid(pid, &status, WUNTRACED); Submission Requirements Submit your source code (Shell script file) and makefile if necessary. Submit a lab report. This includes (from : http://www.columbia.edu/cu/biology/faculty/mowshowitz/howto_guide/lab_report.html) 1. In a formal design document: a. Describe and discuss the structures or classes used by the dispatcher for queuing, dispatching and allocating memory and other resources. b. If your design required memory allocation: Describe and discuss what memory allocation algorithms you could have used and justify your final design choice. c. Describe and justify the overall structure of your program, describing the various modules and major functions (descriptions of the function 'interfaces' are expected). d. Discuss the possible use of a multilevel dispatching scheme, which would combine FCFS for realtime processes and RR or Feedback for prioritized processes. e. Include results from your run and an explanation or interpretation of the output. f. Diagram the flow of control (Gantt diagram) that illustrates the execution of the dispatched processes. g. Discuss turnaround time for each algorithm. 1. Determine (and show how it was calculated) the turnaround time of each process (i.e., how long was it in the system?) 2. Determine the average turnaround time. h. Include the source of our code. i. Include instructions on how to compile and run your code. The formal design document is expected to have in-depth discussions, descriptions and arguments.

Appendix: Feedack Dispatcher Having got the Round Robin dispatcher going, it is now a comparatively simple step to extend your code to make a multi-queue Three Level Feedback Dispatcher (from Stallings Fig 9.10) The logic is very similar to the previous exercise except that instead of enqueueing an incomplete process back onto the same (RR) queue that the process came from, the process is enqueued onto a lower priority process queue (if there is one to receive it). Obviously, the lowest priority queue operates in exactly the same way as a simple Round Robin queue. To make the Feedback dispatcher work in the same way as described in Stallings Figure 9.5 (Feedback q=1) the logic should be: 1. Initialize dispatcher queues (input queue and feedback queues); 2. Fill input queue from dispatch list file; 3. Start dispatcher timer (dispatcher timer = 0); 4. While there's anything in any of the queues or there is a currently running process: i. Unload pending processes from the input queue: While (head-of-input-queue.arrival-time <= dispatcher timer) dequeue process from input queue and enqueue on highest priority feedback queue (assigning it the appropriate priority); ii. If a process is currently running: a. Decrement process remainingcputime; b. If times up: A. Send SIGINT to the process to terminate it; B. Free up process structure memory; c. else if other processes are waiting in any of the feedback queues:

A. Send SIGTSTP to suspend it; B. Reduce the priority of the process (if possible) and enqueue it on the appropriate feedback queue iii. If no process currently running && feedback queues are not all empty: a. Dequeue a process from the highest priority feedback queue that is not empty b. If already started but suspended, restart it (send SIGCONT to it) else start it (fork & exec) c. Set it as currently running process; iv. sleep for one second; v. Increment dispatcher timer; vi. Go back to 4. 5. Exit. or something like that! As you can see, there is really not much difference between this and the Round Robin we completed last week. Try this with the following job list with a quantum of 1 sec: <arrival time>,program name, <priority>,<cputime> 0,P1,3,3 1 st Job: Arrival time 0, priority 1 (Real-Time), requiring 3 seconds of CPU time 2,P2,3,6 2 st Job: Arrival time 2, priority 1 (Real-Time), requiring 6 seconds of CPU time 4,P3,3,4 6,P4,3,5 8,P5,3,2 Appendix: Fair-Share Scheduling Dispatcher Fair-share scheduling [Bach, 1986] is a more abstract strategy for scheduling than any of the three built-in strategies. The idea is that the CPU should be shared among sets of processes according to the groups that own those processes. For example, suppose that Tom, Dick, and Harry belong to different groups and are logged in to a machine that uses fair-share scheduling. Further suppose that Tom has only one runnable process, Dick has three, and Harry has six. Fair-share scheduling calls for ten runnable processes and instead of each process getting 10 of the CPU cycles, the three groups each get one-third of the CPU cycles to allocate to the processes that they own. So Tom's single process would get 33 of the available CPU cycles, each of Dick's three processes would get about 11 of the available CPU cycles, and each of Harry's six processes would get about 5.5 of the CPU cycles. If Betty belonged to Dick's group and she logged in to the machine and created two more processes, then Tom's group would have one process but still receive one-third of the CPU cycles. Dick and Betty would have five processes and would be allocated one-third of the CPU cycles, distributed equally among their five processes, with each receiving about 6.7 of the total machine cycles. Each of Harry's six processes would continue to receive about 5.5 of the available CPU cycles.