Operating Systems (234123) – Spring 2012 (Homework Wet 2) Homework Wet 2 Due date: Tuesday, 08/05/12, 12:30 Teaching assistant in charge: Raja Giryes E-mails regarding this exercise should be sent only to the following email: cs234120@cs.technion.ac.il with the subject line: cs234123hw2_wet. Introduction As we have seen, the kernel tries to imitate SRTF in each scheduling policy. However, the process with highest priority is not always the process that has the shortest remaining time. In addition, within the same priority we always choose the first on the queue though the other processes might have a shortest remaining time. In this assignment you will modify the existing scheduling policy for regular processes, SCHED_OTHER, in the Linux kernel and add randomness to it. This policy will work in two modes. The first mode is the regular one that already exists. The second one will choose processes at random using the existing priorities of each task as its probability of selection. 1. Detailed Description You goal is to change the Linux scheduling algorithm, to support the new modified scheduling policy. The existing scheduling mechanism in SCHED_OTHER will be called MODE_REGULAR while the new mechanism will be called MODE_RANDOM. MODE_REGULAR works exactly as taught in class and you do not need to make any changes for it. Only a regular (SCHED_OTHER) processes might be affected by the new mechanism. You should add a flag to the SCHED_OTHER policy indicating whether it should use the MODE_REGULAR mechanism or the MODE_RANDOM mechanism. When the system starts the default mechanism should be MODE_REGULAR. Changing the flag should be done by the sched_setmechanism() system call. When the mechanism of SCHED_OTHER is changed, the caller of the sched_setmechanism() should also inform the operating system of the randomness parameters p_prio, p_epoch and p_interactive. Those parameters should be in the range of 1 to 100. 1 Operating Systems (234123) – Spring 2012 (Homework Wet 2) MODE_RANDOM mechanism syscall The MODE_RANDOM mechanism differs from the MODE_REGULAR mechanism in the following actions: 1. Selecting the next process to run. 2. Changing epoch. 3. Deciding if task is interactive or not. Selecting the next process to run: In the stage of selecting the next process to run the MODE_RANDOM will choose the highest priority with probability p_prio/100. If the highest priority was not selected then the second priority will be selected with the same probability (globally it will be selected with probability p_prio/100*(1-p_prio/100) and so on. If the scheduling mechanism got to the worst priority it will select it with probability 1. Once a priority is chosen, the mechanism will choose one of the processes in this priority uniformly at random. Taking a concrete example, given that processes A_1, A_2 and A_3 have priority 105, B_1 and B_2 have priority 120 and C_1,C_2,C_3 and C_4 have priority 135 the mechanism will use the following algorithm. First it will select the priority. Priority 105 will be selected with probability p_prio/100. Priority 120 will be selected with probability p_prio/100*(1-p_prio/100). And priority 135 will be selected if neither 105 nor 120 were selected. Given that priority 105 was selected each process will be selected to run with probability 1/3. Given that priority 120 was selected each process will be selected to run with probability 1/2 and given that 135 was selected each process will be selected with probability 1/4. In addition, in case that a process with priority higher than the one of the current running process woke up the scheduler will be invoked with probability p_prio/100. Changing epoch: In the MODE_REGULAR mechanism a change of epoch happens only when the active queue is empty. In the MODE_RANDOM mechanism each time the function schedule is invoked we continue in the same epoch with probability p_epoch/100 and a new epoch starts with probability 1-epoch/100. If a new epoch begins all the processes in the active queue should be moved to the expired queue and then the queues should be exchanged. Deciding if process is interactive or not: MODE_RANDOM will decide if a process is interactive or not using the same criteria like in MODE_REGULAR with the addition of randomness. It will use a macro similar to the one used for MODE_REGULAR which will return the same answer as TASK_INTERACTIVE with probability p_interactive/100 and false otherwise. 2 Operating Systems (234123) – Spring 2012 (Homework Wet 2) Complexity requirements The space complexity of the scheduling process should remain O(n), when n is the number of processes in the system. You should make an effort to have the scheduler as fast as possible. Achieving O(1) time complexity for every possible choice of a process to run is somewhat difficult, But the common case should work fast, and it is required that choosing the next task to run would not usually take as much as O(n). 2. Technicalities New policy You should define a new scheduling mechanism MODE_REGULAR and MODE_RANDOM with the values of 301 and 302 (in the same place where SCHED_OTHER is defined in the kernel and in hw2_syscalls.h in the user). Upon changing the mechanism to MODE_RANDOM using sched_setmechanism(), all of your algorithm-specific variables and data structures should be initialized/updated. If the passed probabilities have illegal values, -1 should be returned, and you should set ERRNO to EINVAL. Things to note: A change of the scheduling mechanism should affect all other regular process. Real time processes should be scheduled as usual. For setting the scheduling mechanism and its parameters and having information about the current policy you should use system calls sched_{get,set}mechanism(). Changing Policy syscall Changing the policy should be done using syscall number 243: int sched_setmechanism(int mode, struct random_params* params); The wrapper will return the previous mechanism (used with sched_other) on success and -1 other wise. mode will get either mode_regular or mode_random. If mode = MODE_RANDOM then params points to a struct that contains p_prio, p_epoch and p_interactive, otherwise it should contain NULL. The probability values should be in the range [1,100]. In case illegal pointer or values were passed in one of the parameter ernno should be set to EINVAL. 3 Operating Systems (234123) – Spring 2012 (Homework Wet 2) syscall number 244: int sched_getmechanism(struct random_params* params); The wrapper will return the mechanism (used with sched_other) used on success and -1 other wise. If mode = MODE_RANDOM then params points to a struct that contains p_prio, p_epoch and p_interactive, otherwise it should contain NULL. In case illegal pointer was passed ernno should be set to EINVAL. The above system calls use the following struct. In the user mode it should be defined in hw2_syscalls.h. In the kernel you can place it wherever you decide. struct random_params { int p_prio; int p_epoch; int p_interactive; }; Querying system calls Define the following system calls to query process status: syscall number 245: int is_interactive(int pid) The wrapper will return 1 if the process with the given pid is interactive and 0 other wise. If pid=0 than the syscall will check whether the current process is interactive or not. In case that the scheduling mechanism is MODE_RANDOM then a process that is supposed to be interactive under MODE_REGULAR will return 1 with probability p_interactive/100 and 0 with probability 1-p_interactive/100 in each call. This means that in two consecutive calls this system call can return different values for the same process depending on the probability. syscall number 246: int get_cur_running_priority(int* best_ready_priority) The wrapper will return the (dynamic) priority of the current running process. It will put in best_ready_priority the best (dynamic) priority that has processes ready to run in the active queue (including the current running process) of the runqueue that belongs to the processor that the current running process is running on. In case of an unsuccessful call (wrong parameters, illegal pointer or any other error) both wrappers should return -1 and update errno accordingly, like any other syscall. If pid is illegal or not found ESRCH should be put in errno. For wrong number in cpu_num or for a wrong address or NULL in best_ready_priority EINVAL should be put in errno. Note that the wrapper for these system calls should use the interrupt 128 to invoke the system_call() method in the kernel mode, like regular system calls. 4 Operating Systems (234123) – Spring 2012 (Homework Wet 2) Scheduling Update the necessary functions to implement the new scheduling algorithm. Note that: - You should not change the function context_switch or the context switch code in the schedule function. - The functionality of the kernel should not be changed apart from what was specified. Producing pseudo-random numbers For having the randomness in the kernel use the following function that generates pseudo-random numbers in the range [0,max_val-1] uniformly (all numbers in the range have the same probability to be generated). unsigned char uniform_random(unsigned char max_val) { random_seed = jiffies* 1103515245 + 12345; return (unsigned char)((unsigned int)(random_seed / 65536) % max_val); } This function can help you to have randomness in the kernel. For example, if you want to select one process among N processes where all have the same probability to be selected then you should use uniform_random(N). If you want to allow an event with probability p/100 where p is integer in the range [1,100] then you should use uniform_random(100) and check whether it is bigger or smaller than p. 3. Testing Monitoring the scheduler To measure the impact of your scheduler, and to see that it really works, you should add a mechanism that collects statistics on your scheduler behavior. For every creation of a process your mechanism should remember the next 30 process switching events that occurred after the creation, and also the same information after a process ends (process ends on calling do_exit() function) and when scheduling mechanism is changed (or edited). So actually on process creation or ending you should start monitoring the next 30 task switching event. From these, remember only the 150 latest task switching events. If during 30 events a process is created or ends then you should record 30 events from the new creation/ending. For example, if a process was created and then after 11 scheduling events another process was created then you have to record in total 41 events. 5 Operating Systems (234123) – Spring 2012 (Homework Wet 2) For each task switching it should have the following information: i. Current scheduling mechanism. ii. The next task pid and its (dynamic) priority. iii. The previous (current) task pid and its (dynamic) priority. iv. The value of the best (dynamic) priority in the active queue (if a new epoch began then you should look on the active queue that contains all the processes). v. Whether a new epoch began (1) or not (0). vi. Time of switching (value of jiffies). vii. Reason of switching should be one of the nine: (if more than one reason is correct, choose the first reason from the list) 1. A task was created (the task next runs for the first time) 2. A task ended. 3. A task yields the CPU. 4. The previous task goes out for waiting. 5. A task with higher priority returns from waiting. 6. The time slice of the previous task has ended. Define in your kernel (wherever you decide) and user mode (in hw2_syscalls.h) a struct that contain the information on a task switching: struct switch_info { int previous_pid; int next_pid; int previous_priority; int next_priority; int best_priority; int is_new_epoch; unsigned long time; int reason; }; Monitoring one task switching should be o(1). Note that a 'would be' context switch, from a process to itself (this could happen if a regular process yielded and was re-selected to run) should also be logged. Add a new system call (+ wrapper), with the following prototype: int get_scheduling_statistic(struct switch_info *); Give get_scheduling_statistic() syscall number 247. This system call gets a pointer to a switch_info array of size 150 in user mode. The system call should fill the array and return the number of elements that were filled, or -1 (and updating errno accordingly) on error. The memory allocation is done by the user. Hint: Use copy_to_user and copy_from_user to copy data from kernel space to user space and vice versa. Use Google, the man pages and the source code to find information about these functions. 6 Operating Systems (234123) – Spring 2012 (Homework Wet 2) Testing program Write a program (call it sched_tester.c) that invokes tasks (using fork). The test program should change the mechanism to SCHED_RANDOM. All tasks should do a recursive calculation of a fibonaci number. (That looks something like this : int fibonaci(int n) { if (n < 2) return n; return fibonaci(n-1) + fibonaci(n-2); } ) They needn't return the result value – just do the calculation. When all tasks are done (use wait() ) the program should call get_scheduling_statistic(), print the output in a clear format (together with the PID's and parameters of the tasks) and finish. The program should get as arguments pairs of integers: sched_tester <p_prio><p_sched><p_interactive> <nice1> <n1> <nice2> <n2>… Where <p_prio>,<p_sched> and <p_interactive> are the parameters for the sched_random mechanism, <nicei> determines the static_prio of the task and <ni> is the fibonaci number it is asked to calculate. Run this program on the following inputs: i. sched_tester 100 100 100 0 10 0 10 0 10 ii. sched_tester 50 50 50 0 10 0 10 0 10 iii. sched_tester 90 90 90 19 20 -20 20 0 20 19 30 -20 30 0 30 Explain the results. How does the algorithm express itself in the result? 4. Important Notes and Tips Reread the tutorial about scheduling and make sure you understand the relationship between the scheduler, its helper functions, the runqueue, waitqueues and context switching. Think and plan before you start – what will you change? What will be the role of each existing field or data structure in the new (combined) algorithm? Note that allocating memory (kmalloc(buf_size, GFP_KERNEL) and kfree(buf)) from the scheduler code is dangerous, because kmalloc may sleep. This exercise can be done without dynamically allocating memory. 7 Operating Systems (234123) – Spring 2012 (Homework Wet 2) You must not use recursion in kernel. The kernel uses a small bounded stack (8KB), thus recursion is out of question. Luckily, you don’t need recursion. You may assume the system has only one CPU (!!!) but still you might need some synchronization, when editing the kernel data-structures. Your solution should be implemented on kernel version 2.4.18-14 as included in RedHat Linux 8.0. A test program simple_test.c is provided for you for having a basic test of your implementation and syntax. Note that the previous is a very basic test. You should test your new scheduler very thoroughly, including every aspect of the scheduler. There are no specific requirements about the tests, inputs and outputs of your thorough test and you should not submit it, but you are very encouraged to do this. 5. Submission The submission of this assignment has two parts: An electronic submission You should create a zip file (use zip only, not gzip, tar, rar, 7z or anything else) containing the following files: a. A tarball named kernel.tar.gz containing all the files in the kernel that you created or modified (including any source, assembly or makefile). To create the tarball, run (inside VMWare): cd /usr/src/linux-2.4.18-14custom tar -czf kernel.tar.gz <list of modified or added files> Make sure you don't forget any file and that you use relative paths in the tar command, i.e., use kernel/sched.c and not /usr/src/linux-2.4.1814custom/kernel/sched.c Test your tarball on a "clean" version of the kernel – to make sure you didn't forget any file b. A file named hw2_syscalls.h containing the syscalls wrappers. c. A file named sched_tester.c containing your test program. d. A file named tester_results.txt containing the output of the sched_tester and to explanations to it. e. A file named submitters.txt which includes the ID, name and email of the participating students. The following format should be used: 8 Operating Systems (234123) – Spring 2012 (Homework Wet 2) Bill Gates bill@t2.technion.ac.il 123456789 Linus Torvalds linus@gmail.com 234567890 Steve Jobs jobs@os_is_best.com 345678901 Important Note: Make the outlined zip structure exactly. In particular, the zip should contain only the 5 files, without directories. You can create the zip by running (inside VMware): zip final.zip kernel.tar.gz sched_tester.c hw2_syscalls.h tester_results.txt submitters.txt The zip should look as follows: zipfile -+ | +| +| +| +| +- kernel.tar.gz submitters.txt sched_tester.c tester_results.txt hw2_syscalls.h A printed submission The printed submission should contain an explanation of the changes you have made. Do not print the electronically-submitted source code. Handwritten assignments will not be accepted. Have a Successful journey, The course staff 9