9
CS61: Systems Programming and Machine Organization Section Notes Week of Nov 9 th Outline for this week: Forks Signal Handlers Threads

Week9nn

Embed Size (px)

DESCRIPTION

ghhihjhjhjhjhjh

Citation preview

Page 1: Week9nn

CS61: Systems Programming and Machine Organization

Section NotesWeek of Nov 9th

Outline for this week:● Forks● Signal Handlers● Threads

Page 2: Week9nn

Forks and HandlersQuestion 1

(i) How many output lines are printed?

void fn() { fork(); fork(); printf("hello\n"); return;}

int main() { fn(); printf("hello\n"); exit(0);}

(ii) How many output lines are printed?

void fn() { if (fork() == 0) { fork(); printf("hello\n");

exit(0); } return;}

int main() { fn(); printf("hello\n"); exit(0);}

(iii) How many output lines are printed?

void fn() { if (fork() == 0) { fork(); printf("hello\n");

return; } return;}

int main() { fn(); printf("hello\n"); exit(0);}

Page 3: Week9nn

(iv) What does this program print?

int counter = 1;

int main() { if (fork() == 0) {

counter--; exit(0);

} else {wait(NULL); counter++; printf("counter = %d\n", counter);

} exit(0);}

Question 2

Consider the following program:

void end(void) {

printf(“2”);

}

int main() {

if (fork() == 0)

atexit(end);

if (fork() == 0)

printf(“0”);

else

printf(“1”);

exit(0);

}

Determine which of the following outputs are possible. Note: The atexit function takes a pointer to a function and adds it to a list of functions (initially empty) that will be called when the exit function is called.

A. 112002

B. 211020

C. 102120

D. 122001

E. 100212

Question 3

Page 4: Week9nn

int counter = 0;

int main() {int i;for (i = 0; i < 2; i ++){ fork(); counter++; printf("counter = %d\n", counter);}

printf("counter = %d\n", counter); return 0;}

(i) How many times is the value of counter printed?

(ii) What is the value of counter printed in the first line?

(iii)What is the value of counter printed in the last line?

Page 5: Week9nn

Question 4

Dixon Hill is thinking of using signals to allow a parent process to count events that occur in a child process. The idea is to notify the parent each time an event occurs by sending it a signal, and letting the parent's signal handler increment a global counter variable, which the parent can then inspect after the child has terminated. However, when he runs the test program shown below on his system, we discovers that when the parent calls printf, counter always has a value of 2, even though the child has sent five signals to the parent. Perplexed, he comes to you for help. Can you explain the bug?

int counter = 0;

void handler(int sig) {

counter++;

sleep(1);

return;

}

int main() {

int i;

Signal(SIGUSR2, handler);

if (Fork() == 0) {

for (i = 0;i < 5;i++) {

Kill(getppid(), SIGUSR2);

printf(“sent SIGUSR2 to parent\n”);

}

exit(0);

}

Wait(NULL);

printf(“counter=%d\n”, counter);

exit(0);

}

Page 6: Week9nn

Question 5

pid_t pid;

int counter = 0;

void handler1(int sig) {counter ++; printf("counter = %d\n", counter);

/* Flushes the printed string to stdout */fflush(stdout); kill(pid, SIGUSR1);

}

void handler2(int sig) {counter += 4; printf("counter = %d\n", counter); exit(0);

}

main() { signal(SIGUSR1, handler1); if ((pid = fork()) == 0) {

signal(SIGUSR1, handler2); kill(getppid(), SIGUSR1); while(1) {};

} else {pid_t p; int status; if ((p = wait(&status)) > 0) {

counter += 2; printf("counter = %d\n", counter);

}}

}

What is this program's output?

Page 7: Week9nn

ThreadsAllow a single program to perform multiple tasks concurrently.

Difference between threads and processes:

Multiple threads (within a process) share memory address space, privileges and all other resources provided by the OS (open files, network sockets... etc.)

What is different between two threads?

CPU register, stack and program counter. These are maintained in the thread control block (TCB).

Challenge: Making sure program executes correctly in all possible interleaving of threads. For example, what happens when you run the following C program?

#include "csapp.h"

#define NITERS 2000000

void *count(void *arg);

unsigned int cnt = 0; /* shared counter variable */

int main() {

pthread_t tid1, tid2;

Pthread_create(&tid1, NULL, count, NULL);

Pthread_create(&tid2, NULL, count, NULL);

Pthread_join(tid1, NULL);

Pthread_join(tid2, NULL);

if (cnt != (unsigned)NITERS*2)

printf("BOOM! cnt=%d\n", cnt);

else

printf("OK cnt=%d\n", cnt);

exit(0);

}

void *count(void *arg) { /* thread routine */

int i;

for (i = 0; i < NITERS; i++)

cnt++;

return NULL;

}

Page 8: Week9nn

# Run the program over and over

$ sh test.sh

OK cnt=4000000

BOOM! cnt=3490653

BOOM! cnt=3471683

BOOM! cnt=3404617

...

Part of disassembly of the for loop code of function count():

C:

for (i = 0; i < NITERS; i++)

cnt++;

Assembly:

.L12:

movl cnt, %eax #L: Load cnt

leal 1(%eax), %eax #U: Update cnt

movl %eax, cnt #S: Store cnt

Interleaving 1:

Step Thread Instruction %eax1 %eax2 cnt

1 1 L1 0 - 0

2 1 U1 1 - 0

3 1 S1 1 - 1

4 2 L2 - 1 1

5 2 U2 - 2 1

6 2 S2 - 2 2

7 1 L1 2 - 2

8 1 U1 3 - 2

9 1 S1 3 - 3

Interleaving 2:

Step Thread Instruction %eax1 %eax2 cnt

1 1 L1 0 - 0

2 1 U1 1 - 0

3 2 L2 - 0 0

4 1 S1 1 - 1

5 2 U2 - 1 1

6 2 S2 - 1 1

7 1 L1 1 - 1

8 1 U1 2 - 1

9 1 S1 2 - 2

In the next few lectures we'll cover ways to synchronize threads to avoid this problem.

Page 9: Week9nn

AnswersQuestion 1:

(i) 8 lines(ii) 3 lines(iii)5 lines(iv)counter = 2

Question 2:A, C, and E are possible results. The rest are not.

Question 3:(v) 10(vi) 1(vii) 2

Question 4:Signals cannot be used to count events in other processes because signals are not queued. Solving this problem requires inter-process communication (IPC) mechanisms.

Question 5:Counter = 1Counter = 4Counter = 3