Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Spring 2019
1
If you want to do one task
• Start one process
P1
If you want to do two task “concurrently”
• Start two processes
• Maybe P1 forks P2
• and P3…PN etc if
more than two tasks
P1 P2
• Problem:
• fork is expensive
• cold-start penalty
If P1 and P2 want to talk to each other?
• E.g. access the same data or
synchronize?
• Two different address spaces
• Need to use IPC
• shared memory, pipes, sockets,
signals
• Problem
P1 IPC P2
• kernel transitions are expensive
• May need to copy data
• user—->kernel—>user
• Inter-process Shared memory is
a pain to set up.
Option 1:Event-driven programming
• Make one process do all the tasks
P1
• Busy loop polls for events and
executes tasks for each event
while(1)
• No IPC needed
{
• Length of the busy loop determines if (event 1) do task 1;
response latency if (event 2) do task 2;
…
• Stateful event responses complicate if (event N) do task N;
the code }
• What if ith occurrence of event 1
effects the jth event processing ?
Option 2: Use threads
• Multiple threads of execution per
process
• Each thread has its own
• Program counter P1
• Stack, stack pointer Shared address space
• Registers
• All threads share
• one virtual address space
• code, heap and static data
• Lower context switching overhead
• No IPC
• Zero data transfer cost
• Only need inter-thread T1 T2 T3 T4
syncrhonization
Other Shared and non-shared components
• Shared components
• Open descriptors (files, sockets etc)
• Signals and Signal handlers
• Not shared
• Thread ID
• Errno
• Priority
Address space layout
Example: A word processor with three threads
• No Inter-process communication
• Zero data transfer cost between threads
• Only need inter-thread synchronization
• Lack of robustness
• Crash in one thread will crash the entire process.
19
Pthread API: process identification
• A thread can obtain its own thread ID by calling the
pthread_self() function.
• Why are the argument and the return value are made as void
pointer?
• To pass multiple arguments or return multiple values
• For example, if we need to pass multiple arguments to
start, then arg can be specified as a pointer to a structure
containing the arguments as separate fields.
• The return value of the thread start function is also a void
pointer (void *). It can be captured by pthread_join().
24
Pthread API: thread creation
26
Pthread API: thread termination
30
31
Pthread API: detaching a thread
• By default, a thread is joinable, meaning that when it
terminates, another thread can obtain its return status
using pthread_join().
• If don’t care about the thread’s return status and want
the system to automatically clean up and remove the
thread when it terminates.
• In this case, we can mark the thread as detached, by
making a call to pthread_detach() specifying the
thread’s identifier in thread.
32
int idata = 111; /* Allocated in data segment */
childPid = fork();
if (childPid == -1) {exit(-1);}
else if (childPid == 0) {idata *= 333; istack *= 666;} /* Child Process: modify data */
else {sleep(3)} /* Parent process: give child a chance to execute */
exit(0);
}
33
int idata = 111; /* Allocated in data segment */
sleep(1);
printf(“idata=%d istack=%d\n”, idata, istack);
exit(0); ?
}
idata=333
34
Threads race condition: sharing data
35
What we expect …
But actually …
36
Source of the problem: uncontrolled
scheduling and unprotected shared data
37