2. (3 pts.) Mention in what circumstances the user time of a process
may exceed the real time.
3. (3 pts.) Write the factors used to determine the length of a quantum.
4. (3 pts.) Give the reasons why system calls are implemented using
software interrutps.
5. (3 pts.) What are the advantages and disadvantages of preemptive
vs. non-preemptive scheduling.
6. (10 pts.) Implement the code for the following function
char *strstr(const char *haystack, const char *needle) The strstr() function finds the first occurrence of the substring needle in the string haystack. The terminating `\0' characters are not compared. The strstr() function returns a pointer to the beginning of the substring, or NULL if the substring is not found. |
char *strstr(const char *haystack, const char *needle) { } |
7. (10 pts.) Write the implementation of the procedure getenv() that returns the value of an environment variable or NULL if that variable does not exist. |
extern char ** environ; char * getenv( char * var_val ) { } |
8. (10 pts.) The add() method adds a number to a linked list of integers. This add method does not have mutexes. Thread T1 calls add(5) and thread T2 calls add(7) at the same time. Give a sequence of instructions (use the labels a, b, c, d) that can cause the node with the "7" value to be lost. |
struct Node { int _val; Node * _next; }; class IntList { Node * _head; IntList() { _head = NULL; } void add( int val ) { a) Node * n = new Node() b) n->_val = val; c) n->next = _head; d) _head = n; } } t --------------------------------> T1 -> T2 -> |
9. (5 pts) Write a synchronized bounded buffer class with a circular buffer where the writer thread that calls add(int val) will block if the buffer is full. The reader thread calling remove() will block if the bounded buffer is empty. The constructor BoundedBuffer(int max) allocates space for _buffer with max size elements and it also initializes semaphores. Add also the semaphores and mutexes that are necessary. |
class BoundedBuffer { int * _buffer; int _max; int _head; int _tail; // More variables or semaphores if necessary BoundedBuffer( int max ) { } void add( int val ) { // Block if buffer is full } int remove() { // Block if buffer is empty } |
10. (10 pts.) Write a function redirectOutput(args, outfile) that will execute the program in args[0] in a separate process and it will redirect the output to the file named outfile. args is an array of arguments where args[0] is the program to run and the last aregument is a NULL pointer. You will have to implement the procedure in two ways: 1. Do the reedirection in the parent. and 2. Do the redirection in the child.The procedure will return 0 if success or different than 0 otherwise. |
int redirectOutput(char ** args, char * outfile) { // Do the redirection in the parent } int redirectOutput(char ** args, char * outfile) { // Do the redirection in the child } |
11. Implement the procedure int runpipe( char ** args1, char ** args2) that runs the programs in args1 and args2 in different children processes where the output of args1 goes to the input of args2 using a pipe. args1 and args2 are arrays of arguments where the last argument is NULL. The element args1[0] and args2[0] are the names of the programs to execute. runpipe() will return 0 if success or different than 0 otherwise. |
int runpipe( char ** args1, char ** args2) { } |
12. (10 pts.) Implement a name table class using an array of TableEntry
struct's. The constructor NameTable(max) will allocate space for a table
with n entries. The function add(var,val) will block until there is space
in the table, then it will search for an entry in the table that is unused
( _var and _val are NULL) and it will add the var and val strings
in that entry. Duplicated values are allowed.
The function lookup(var) will lookup the string var in the table and it will return the corresponding value. If the variable does not exist, lookup() will wait until that variable is added with the add() function. Add the semaphores and mutexes that are necessary and the code that implements the behavior described. |
struct TableEntry { char * _var; char * _val; // Other variables here }; class NameTable { // Max length of table int _max; // Array of TableEntry entries TableEntry * _table; // Other variables here public: NameTable(int max) { } void add(char *var, char *val) { } char * lookup(char * var) { } }; |