Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

CS 202: Advanced Operating Systems

Lab #1: System Call Implementation

In this assignment, you will add two new system calls that provide the information of the system and the target process, respectively.

Part 1: sysinfo

Add a new system call int sys info(int param) that takes as input one integer parameter of value 1, 2 or 3. Depending on the input value, it returns:

.    If param == 0: the total number of active processes (ready, running, waiting, or zombie) in the system .

.    If param == 1: the total number of system calls that has made so far since the system boot up. Do not include the current sysinfo syscall’s attempt when returning the number.

.    Example: Suppose the system has made 5 syscalls so far. sysinfo should return 5 as output , instead of 6. If sysinfo is called again right after this , then it should return 6.

.    If param == 2: the number of free memory pages in the system. If there is one free page left, the return value should be 1 (= 1 page) .

.    Otherwise: return error (- 1)

Part 2: procinfo

Add a new system call int proc info(struct pinfo *in) that provides information specific to the current process (= caller process of this syscall). It takes as input a pointer of struct pinfo and fills     out the fields of this struct:

1 struct pinfo {

2 int ppid;

3 int syscall_count;

4 int page_usage;

5 };

.    int ppid: the PID of its parent process .

.     int syscall_count: the total number of system calls that the current process has made so far . Do not include the current sysinfo syscall’s attempt when returning the number.

.     int page_usage: the current process’s memory size in pages (e.g., 10000 bytes à 3 pages) .

procinfo() returns 0 on success; - 1 otherwise (e.g., NULL input pointer, fail to copy results back to the caller process , etc.)

Tips:

.    To count the number of processes, see kernel/proc.c and   kernel/proc.h

.    To check the system call count, you will need to modify kernel/syscall.c

.    Even if sysinfo() is the very first syscall you make in your user-level program, you will notice that a couple of other syscalls have been already issued. This is normal; recall how a process is

created (e.g., fork, exec, etc).

.     printf uses syscalls to display output. So you may see an unexpected increase in syscall count when printf is inserted in-between sysinfo or procinfo.

.    To check the amount of free memory pages in the system , see kernel/kalloc.c. Xv6 manages free pages in a linked list (kmem.freelist) .

.    To retrieve a pointer type input in a syscall, use argaddr(). The kernel cannot directly write     data to the userspace memory; you will need to use copyout() to do so. Search the kernel code to find how to use copyout (e.g., kernel/file.c or sysfile.c) .

.    The kernel function  myproc() returns the PCB of the current process.

.    To implement Part 2, you need to manage syscall count on a per-process basis. Initialize new per- process data fields in allocproc().

.    You can find the amount of memory used by each process from its PCB.

.    To check if your syscall is reporting the correct number of free or used memory, allocate memory in your user-level program before making the system call.

How to test:

To test your implementation , you can create a user-level program using these syscalls under various scenarios . Below is just an example (user/lab1_test.c):

1

2

3

4

5

6

7

8

9

10

11

12

13

#include "kernel/types.h"

#include "kernel/stat.h"

#include "user/user.h"

#define MAX_PROC 10

struct pinfo {

int ppid;

int syscall_count;

int page_usage;

};

void print_sysinfo(void)

{

int n active proc, n syscalls, n free pages;

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

n_active_proc = sysinfo(0);

n_syscalls = sysinfo(1);

n_free_pages = sysinfo(2);

printf("[sysinfo] active proc: %d, syscalls: %d, free pages: %d\n",

n_active_proc, n_syscalls, n_free_pages);

}

int main(int argc, char *argv[])

{

int mem, n_proc, ret, proc_pid[MAX_PROC];

if (argc < 3) {

printf("Usage: %s [MEM] [N_PROC]\n", argv[0]);

exit(-1);

}

mem = atoi(argv[1]);

n_proc = atoi(argv[2]);

if (n_proc > MAX_PROC) {

printf("Cannot test with more than %d processes\n", MAX_PROC);

exit(-1);

}

print_sysinfo();

for (int i = 0; i < n_proc; i++) {

sleep(1);

ret = fork();

if (ret == 0) { // child process

struct pinfo param;

malloc(mem); // this triggers a syscall

for (int j = 0; j < 10; j++)

procinfo(¶m); // calls 10 times

printf("[procinfo %d] ppid: %d, syscalls: %d, page usage: %d\n",

getpid(), param.ppid, param.syscall_count, param.page_usage);

while (1);

}

else { // parent

proc_pid[i] = ret;

continue;

}

}

sleep(1);

print_sysinfo();

for (int i = 0; i < n_proc; i++) kill(proc_pid[i]);

exit(0);

}

This user program calls sysinfo() and creates N child processes, each of which allocates a specified amount of memory and calls procinfo(). Once all child processes print procinfo(), the parent process calls sysinfo() again .

For example, if you want to test with 2 child processes with each allocating 65Kbytes of memory, type:

$ lab2_test 65536 2

(the first argument is the bytes of memory to be allocated by each child process, and the second argument is the number of child processes to be created) .

Running example (you may need to press ‘enter’ or any key after each line is printed):

$ lab1_test 65536 2

[sysinfo] active proc: 3, syscalls: 49, free pages: 32564

[procinfo 4] ppid: 3, syscalls: 10, page usage: 21

[procinfo 5] ppid: 3, syscalls: 10, page usage: 21

[sysinfo] active proc: 5, syscalls: 241, free pages: 32510

$ $ $ $ lab1_test 65000 1

[sysinfo] active proc: 3, syscalls: 345, free pages: 32564

[procinfo 10] ppid: 9, syscalls: 10, page usage: 20

[sysinfo] active proc: 4, syscalls: 474, free pages: 32538

$ $ $

What to submit:

You need to submit the following:

(1)  The entire XV6 source code with your modifications (‘make clean’ to reduce the size before submission)

(2) A report (must be in PDF; no other formats will be accepted) including:

a)   The list of all files modified

b)   A detailed explanation on what changes you have made and screenshots showing your work and results

c)   A detailed description of XV6 source code (including your modifications) about how the info system call is processed, from the user-level program into the kernel code, and then back into the user-level program.

d)   Link to the demo video on the very first page of the report.

e)   A brief summary of the contributions of each member

(3) A demo video showing that all the functionalities you implemented works as expected, as if you were demonstrating your work in-person. For instructions about recording, refer to the Demo

Video Recording Guide.

How to submit:

Upload the demo video to your own Google Drive (or YouTube) and create a shareable link. Add this link to the first page of the report. Pack the report and source code files into a single zip file, and upload it to    eLearn/Canvas.

Only one person of your team needs to submit the file.

Grades breakdown:

.    sysinfo() system call: 25 pts

.    procinfo() system call: 25 pts

-     Correct implementation and functionalities of syscalls; correct return values

.    Report: 10 pts

-     Clear and detailed explanation of the changes made

.    Demo video: 10 pts

Total: 70 pts

Academic Integrity:

.    Your submission should be strictly of your own .

.    All submissions will be monitored for similarities with current and previous terms’ submissions .

.    Any similarities found will be escalated as per Academic Misconduct policy:

http://conduct.ucr.edu/policies/academicintegrity.html