The exam was given on Canvas with the Lockdown Browser and Respondus Monitor.
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_signal(pthread_cond_t *cond); int scanf(const char *restrict format, ...); /* Returns the number of successful matches it made. */ int fork(); int execlp(const char *file, const char *arg0, ... /*, (char *)0 */); int wait(int *stat_loc); int dup2(int fildes, int fildes2); int pipe(int fildes[2]); int close(int fildes); int kill(pid_t pid, int sig); unsigned alarm(unsigned seconds); typedef void (*sig_t) (int); sig_t signal(int sig, sig_t func);
For this question, please assume that malloc() is implemented as described in lecture, with four-byte pointers, and free list structures composed of size, flink and blink, in that order. You are given the following facts:
Address: 0x147e18 Size: 32 (0x20) Address: 0x147e58 Size: 48 (0x30) Address: 0x147db8 Size: 32 (0x20) Address: 0x147d58 Size: 40 (0x28)Please answer the following questions. Please put your answer to each question on its own line, in the format `question number: answer`. Also, if your answer is in hex, please precede it with '0x'
1: Consider the allocated memory chunk with the smallest address (not the smallest size, but the smallest address). What is the starting address of that chunk?
2: Consider the allocated memory chunk with the largest address (not the largest size, but the largest address). What is the starting address of that chunk?
3: What is the value at address 0x147d58?
4: What is the value at address 0x147e5c?
5: What is the value at address 0x147e60?
6: There is an allocated memory chunk that begins at address 0x147dd8, and is 64 bytes in size. When the user called malloc() and got this chunk, what value was returned to the user?
7: When the user called malloc() and got this chunk, tell me a legal value of the argument that the user could have given to the malloc() call.
8: If I call sbrk(0), it will return 0x147f58. If I try to write to this address, I won't get a seg fault? Why? Make your answer fit on one line.
int close(int fildes); int fork(); int pipe(int fildes[2]); int write(int fildes, const void *buf, size_t nbyte); int wait(int *status);
How many lines are printed by the following program:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { char *s = "Luther"; char *x; for (x = s; *x != '\0'; x++) fork(); printf("Fred\n"); return 0; } |
Now, you're not really writing this program, but instead you're going to be answering questions about it. When we run it, there will be three processes, which we will name "E" for slencode, "D" for sldecode, and "Y" for yours. You should assume that there is a variable "int p[2]" which is used for a pipe. If you want to use a second pipe, then use a variable "int p2[2]".
As always, in your answer box, please put each answer on one line, preceded with its question number. If there are multiple answers to a question, or the question calls for a one to two sentence answer, please put that all on one line, preceded with the question number.
Question 1: Which process(es) calls pipe()?
Question 2: How does the "E" process know that it's the "E" process?
Question 3: Exactly what dup2() calls are made by the Y process?
Question 4: Exactly what dup2() calls are made by the E process?
Question 5: Exactly what dup2() calls are made by the D process?
Question 6: Exactly what close() calls are made by the E process?
Question 7: Exactly what execlp() call is made by the E process?
Question 8: How would you use threads in this problem? Please give me a two sentence answer.
Question 9: If you didn't use threads, explain how you would use a signal handler and/or the alarm system call for this problem? Please give me a one to three sentence answer.
UNIX> cat input.txt 2 1 5 1 4 UNIX> ./a.out 3 < input.txt 0: Main 1: Thread 0 3: Main 4: Thread 1 5: Main 6: Thread 2 11: Main 12: Thread 0 13: Main 14: Thread 1 18: Main UNIX>And here's the code. BTW, this is not a useful program. I'm just wanting you to demonstrate to me your understanding of the synchronization primitives in pthreads.
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> struct Shared { pthread_mutex_t *lock; pthread_cond_t **cvs; pthread_cond_t *main_cv; long base_time; }; struct Private { int id; struct Shared *s; }; void *thread(void *a) { struct Private *p; struct Shared *s; int num; p = (struct Private *) a; s = (struct Shared *) p->s; /* Missing Thread Code */ } int main(int argc, char **argv) { pthread_t *tids; struct Shared *s; struct Private *p; int i; int n; void *v; if (argc != 2) { fprintf(stderr, "usage: tp num-threads.\n"); return 1; } n = atoi(argv[1]); tids = (pthread_t *) malloc(sizeof(pthread_t) * n); s = (struct Shared *) malloc(sizeof(struct Shared)); s->base_time = time(0); s->lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); pthread_mutex_init(s->lock, NULL); s->main_cv = (pthread_cond_t *) malloc(sizeof(pthread_cond_t)); pthread_cond_init(s->main_cv, NULL); s->cvs = (pthread_cond_t **) malloc(sizeof(pthread_cond_t *) * n); for (i = 0; i < n; i++) { s->cvs[i] = (pthread_cond_t *) malloc(sizeof(pthread_cond_t)); pthread_cond_init(s->cvs[i], NULL); } for (i = 0; i < n; i++) { p = (struct Private *) malloc(sizeof(struct Private)); p->id = i; p->s = s; pthread_create(tids+i, NULL, thread, (void *) p); } /* Missing Main Code */ } |
Example:
UNIX> ./a.out 4 I'm Ready I'm Ready I'm Ready I'm Ready I'm Ready Too # At this point, all five threads are spinning on while(1) loops.