21
– 1 – 15-213, F’02 Traditional View of a Process Process = process context + code, data, and stack shared libraries run-time heap 0 read/write data Program context: Data registers Condition codes Stack pointer (SP) Program counter (PC) Kernel context: VM structures Descriptor table brk pointer Code, data, and stack read-only code/data stack SP PC brk Process context

Traditional View of a Process

  • Upload
    oleg

  • View
    18

  • Download
    0

Embed Size (px)

DESCRIPTION

Traditional View of a Process. Process = process context + code, data, and stack. Process context. Code, data, and stack. stack. Program context: Data registers Condition codes Stack pointer (SP) Program counter (PC) Kernel context: VM structures Descriptor table - PowerPoint PPT Presentation

Citation preview

Page 1: Traditional View of a Process

– 1 – 15-213, F’02

Traditional View of a ProcessTraditional View of a Process

Process = process context + code, data, and stack

shared libraries

run-time heap

0

read/write data

Program context: Data registers Condition codes Stack pointer (SP) Program counter (PC)Kernel context: VM structures Descriptor table brk pointer

Code, data, and stack

read-only code/data

stackSP

PC

brk

Process context

Page 2: Traditional View of a Process

– 2 – 15-213, F’02

Alternate View of a ProcessAlternate View of a Process

Process = thread + code, data, and kernel context

shared libraries

run-time heap

0

read/write dataThread context: Data registers Condition codes Stack pointer (SP) Program counter (PC)

Code and Data

read-only code/data

stackSP

PC

brk

Thread (main thread)

Kernel context: VM structures Descriptor table brk pointer

Page 3: Traditional View of a Process

– 3 – 15-213, F’02

A Process With Multiple ThreadsA Process With Multiple ThreadsMultiple threads can be associated with a process

Each thread has its own logical control flow (sequence of PC values)

Each thread shares the same code, data, and kernel context Each thread has its own thread id (TID)

shared libraries

run-time heap

0

read/write dataThread 1 context: Data registers Condition codes SP1 PC1

Shared code and data

read-only code/data

stack 1

Thread 1 (main thread)

Kernel context: VM structures Descriptor table brk pointer

Thread 2 context: Data registers Condition codes SP2 PC2

stack 2

Thread 2 (peer thread)

Page 4: Traditional View of a Process

– 4 – 15-213, F’02

Logical View of ThreadsLogical View of Threads

Threads associated with a process form a pool of peers. Unlike processes which form a tree hierarchy

P0

P1

sh sh sh

foo

bar

T1

Process hierarchyThreads associated with process foo

T2T4

T5 T3

shared code, dataand kernel context

Page 5: Traditional View of a Process

– 5 – 15-213, F’02

Concurrent Thread ExecutionConcurrent Thread Execution

Two threads run concurrently (are concurrent) if their logical flows overlap in time.

Otherwise, they are sequential.

Examples: Concurrent: A & B, A&C Sequential: B & C

Time

Thread A Thread B Thread C

Page 6: Traditional View of a Process

– 6 – 15-213, F’02

Threads vs. ProcessesThreads vs. Processes

How threads and processes are similar Each has its own logical control flow. Each can run concurrently. Each is context switched.

How threads and processes are different Threads share code and data, processes (typically) do not. Threads are somewhat less expensive than processes.

Process control (creating and reaping) is twice as expensive as thread control.

Linux/Pentium III numbers:

» ~20K cycles to create and reap a process.

» ~10K cycles to create and reap a thread.

Page 7: Traditional View of a Process

– 7 – 15-213, F’02

The Pthreads "hello, world" ProgramThe Pthreads "hello, world" Program/* * hello.c - Pthreads "hello, world" program */#include "csapp.h"

void *thread(void *vargp);

int main() { pthread_t tid;

Pthread_create(&tid, NULL, thread, NULL); Pthread_join(tid, NULL); exit(0);}

/* thread routine */void *thread(void *vargp) { printf("Hello, world!\n"); return NULL;}

Thread attributes (usually NULL)

Thread arguments(void *p)

return value(void **p)

Page 8: Traditional View of a Process

– 8 – 15-213, F’02

Execution of Threaded“hello, world”Execution of Threaded“hello, world”

main thread

peer thread

return NULL;main thread waits for peer thread to terminate

exit() terminates

main thread and any peer threads

call Pthread_create()

call Pthread_join()

Pthread_join() returns

printf()

(peer threadterminates)

Pthread_create() returns

Page 9: Traditional View of a Process

– 9 – 15-213, F’02

Pros and Cons of Thread-Based DesignsPros and Cons of Thread-Based Designs

+ Easy to share data structures between threads e.g., logging information, file cache.

+ Threads are more efficient than processes.

--- Unintentional sharing can introduce subtle and hard-to-reproduce errors! The ease with which data can be shared is both the greatest

strength and the greatest weakness of threads.

Page 10: Traditional View of a Process

– 10 – 15-213, F’02

Shared Variables in Threaded C ProgramsShared Variables in Threaded C ProgramsQuestion: Which variables in a threaded C program are

shared variables? The answer is not as simple as “global variables are shared”

and “stack variables are private”.

Requires answers to the following questions: What is the memory model for threads? How are variables mapped to memory instances? How many threads reference each of these instances?

Page 11: Traditional View of a Process

– 11 – 15-213, F’02

Threads Memory ModelThreads Memory Model

Conceptual model: Each thread runs in the context of a process. Each thread has its own separate thread context.

Thread ID, stack, stack pointer, program counter, condition codes, and general purpose registers.

All threads share the remaining process context. Code, data, heap, and shared library segments of the process virtual

address space. Open files and installed handlers

Operationally, this model is not strictly enforced: While register values are truly separate and protected.... Any thread can read and write the stack of any other thread.

Mismatch between the conceptual and operation model is a source of confusion and errors.

Page 12: Traditional View of a Process

– 12 – 15-213, F’02

Thread SafetyThread Safety

Functions called from a thread must be thread-safe.

We identify four (non-disjoint) classes of thread-unsafe functions: Class 1: Failing to protect shared variables. Class 2: Relying on persistent state across invocations. Class 3: Returning a pointer to a static variable. Class 4: Calling thread-unsafe functions.

Page 13: Traditional View of a Process

– 13 – 15-213, F’02

Thread-Unsafe FunctionsThread-Unsafe Functions

Class 1: Failing to protect shared variables. Fix: Use semaphore operations. Issue: Synchronization operations will slow down code.

Page 14: Traditional View of a Process

– 14 – 15-213, F’02

Thread-Unsafe Functions (cont)Thread-Unsafe Functions (cont)Class 2: Relying on persistent state across multiple

function invocations. Random number generator relies on static state Fix: Rewrite function so that caller passes in all necessary

state.

/* rand - return pseudo-random integer on 0..32767 */ int rand(void) { static unsigned int next = 1; next = next*1103515245 + 12345; return (unsigned int)(next/65536) % 32768; } /* srand - set seed for rand() */ void srand(unsigned int seed) { next = seed; }

Page 15: Traditional View of a Process

– 15 – 15-213, F’02

Thread-Unsafe Functions (cont)Thread-Unsafe Functions (cont)Class 3: Returning a ptr to

a static variable.

Fixes: 1. Rewrite code so caller

passes pointer to struct.» Issue: Requires

changes in caller and callee.

2. Lock-and-copy» Issue: Requires only

simple changes in caller (and none in callee)

» However, caller must free memory.

hostp = Malloc(...));gethostbyname_r(name, hostp);

struct hostent *gethostbyname(char name){ static struct hostent h; <contact DNS and fill in h> return &h;}

struct hostent *gethostbyname_ts(char *p) { struct hostent *q = Malloc(...); P(&mutex); /* lock */ p = gethostbyname(name); *q = *p; /* copy */ V(&mutex); return q;}

Page 16: Traditional View of a Process

– 16 – 15-213, F’02

Thread-Unsafe FunctionsThread-Unsafe Functions

Class 4: Calling thread-unsafe functions. Calling one thread-unsafe function makes an entire function

thread-unsafe.

Fix: Modify the function so it calls only thread-safe functions

Page 17: Traditional View of a Process

– 17 – 15-213, F’02

Reentrant FunctionsReentrant FunctionsA function is reentrant iff it accesses NO shared variables when called from multiple threads.

Reentrant functions are a proper subset of the set of thread-safe functions.

NOTE: The fixes to Class 2 and 3 thread-unsafe functions require modifying the function to make it reentrant.

Reentrantfunctions

All functions

Thread-unsafefunctions

Thread-safefunctions

Page 18: Traditional View of a Process

– 18 – 15-213, F’02

Thread-Safe Library FunctionsThread-Safe Library Functions

All functions in the Standard C Library (at the back of your K&R text) are thread-safe. Examples: malloc, free, printf, scanf

Most Unix system calls are thread-safe, with a few exceptions:

Thread-unsafe function Class Reentrant versionasctime 3 asctime_rctime 3 ctime_rgethostbyaddr 3 gethostbyaddr_rgethostbyname 3 gethostbyname_rinet_ntoa 3 (none)localtime 3 localtime_rrand 2 rand_r

Page 19: Traditional View of a Process

– 19 – 15-213, F’02

RacesRaces

A race occurs when the correctness of the program depends on one thread reaching point x before another thread reaches point y.

/* a threaded program with a race */int main() { pthread_t tid[N]; int i; for (i = 0; i < N; i++) Pthread_create(&tid[i], NULL, thread, &i); for (i = 0; i < N; i++) Pthread_join(tid[i], NULL); exit(0);}

/* thread routine */void *thread(void *vargp) { int myid = *((int *)vargp); printf("Hello from thread %d\n", myid); return NULL;}

Page 20: Traditional View of a Process

– 20 – 15-213, F’02

deadlockregion

DeadlockDeadlock

P(s) V(s)

V(t)

Thread 1

Thread 2

Initially, s=t=1

P(t)

P(t) V(t)

forbiddenregion for s

forbiddenregion for t

P(s)

V(s) deadlockstate

Locking introduces thepotential for deadlock: waiting for a condition that will never be true.

Any trajectory that entersthe deadlock region willeventually reach thedeadlock state, waiting for either s or t to become nonzero.

Other trajectories luck out and skirt the deadlock region.

Unfortunate fact: deadlock is often non-deterministic.

Page 21: Traditional View of a Process

– 21 – 15-213, F’02

Threads SummaryThreads Summary

Threads provide another mechanism for writing concurrent programs.

Threads are growing in popularity Somewhat cheaper than processes. Easy to share data between threads.

However, the ease of sharing has a cost: Easy to introduce subtle synchronization errors. Tread carefully with threads!

For more info: D. Butenhof, “Programming with Posix Threads”, Addison-

Wesley, 1997.