Multithread API’s Adam Piotrowski Grzegorz Jabłoński Lecture III.

Post on 16-Dec-2015

223 views 0 download

transcript

Multithread API’s

Adam PiotrowskiGrzegorz Jabłoński

Lecture III

Agenda• Signals – software asynchronous

interrupts

• Processes

• Threads

2

Signals

• Signals are software interrupts that provide a mechanism for handling asynchronous events.

• The kernel can perform one of three actions:– ignore – catch and handle– perform default action

3

Type of signals

Signal Name Description

SIGCHLD Child has terminated Ignored

SIGINT User generated the interrupt character (Ctrl-C)

Terminate

SIGALRM Sent by alarm() Terminate

SIGUSR1 Process-defined signal Terminate

SIGKILL Uncatchable process termination

Terminate

SIGPIPE Process wrote to a pipe but there are no readers

Terminate

SIGABRT Sent by abort() Terminate with core dump

SIGSEGV Memory access violation Terminate with core dump 4

Signal handling

NAMEsignal - simplified software signal facilities  

SYNOPSIS#include <signal.h> void (* signal(int sig, void *func)(int)))(int);

typedef void (*sig_t) (int); sig_t signal(int sig, sig_t func);

5

Signals - Examplestatic void sigint_handler (int signo){

printf ("Caught SIGINT!\n");exit (EXIT_SUCCESS);

}

int main (void){

if (signal (SIGINT, sigint_handler) == SIG_ERR) {fprintf (stderr, "Cannot handle SIGINT!\n");exit (EXIT_FAILURE);

}for (;;)

pause ( );return 0;

}

6

Processes

• Processes are object code in execution: active, alive, running programs.

• Processes consist of data, resources, state, and a virtualized computer.

7

Multi processes application

8

parent process

child process

child process child process

child process

forkfork

fork fork

fork NAME

fork -- create a new process

SYNOPSIS

#include <sys/types.h>#include <unistd.h>

pid_t fork(void);

9

fork example

pid_t pid;pid = fork();if (pid < 0)

ASSERT(false)else if (pid > 0) {

printf(” Parent process”);}else if (pid == 0){

printf(”Child process”);}

• variables are duplicated

• descriptors are duplicated, too

10

fork example

pid_t pid;pid = fork();if (pid < 0)

ASSERT(false)else if (pid > 0) {

printf(” Parent process”);}else if (pid == 0){

printf(”Child process”);}

11

pid_t pid;pid = fork();if (pid < 0)

ASSERT(false)else if (pid > 0) {

printf(” Parent process”);}else if (pid == 0){

printf(”Child process”);}

fork exampleint sock;while (1){

/*wait for connection from clientestabilish communication with clientsock = …

*/pid_t pid;pid = fork();if (pid < 0)

ASSERT(false)else if (pid > 0) {

close(sock);}else if (pid == 0){

/*perform data exchange based on sock descriptor*/ close(sock); return 0;}

}12

Copy-on-Write

13

processes & SIGCHLD signal

14

processes & SIGCHLD signalint sock;

while (1){ /*

wait for connection from clientestabilish communication with clientsock = …

*/pid_t pid;pid = fork();if (pid < 0)

ASSERT(false)else if (pid > 0) {

close(sock);}else if (pid == 0){

/*perform data exchange based on sock descriptor*/ close(sock); return 0;}

}15

processes & SIGCHLD signalint sock;

if (signal (SIGCHLD, sigint_handler) == SIG_ERR) ASSERT(false);

while (1){ /*

wait for connection from clientestabilish communication with clientsock = …

*/pid_t pid;pid = fork();if (pid < 0)

ASSERT(false)else if (pid > 0) {

close(sock);}else if (pid == 0){

/*perform data exchange based on sock descriptor*/ close(sock); return 0;}

}16

processes & SIGCHLD signalint sock;

if (signal (SIGCHLD, sigint_handler) == SIG_ERR) ASSERT(false);

while (1){ /*

wait for connection from clientestabilish communication with clientsock = …

*/pid_t pid;pid = fork();if (pid < 0)

ASSERT(false)else if (pid > 0) {

close(sock);}else if (pid == 0){

/*perform data exchange based on sock descriptor*/ close(sock); return 0;}

}17

static void sigint_handler (int signo){

int status;wait(&status);

}

processes & SIGCHLD signalint sock;

if (signal (SIGCHLD, sigint_handler) == SIG_ERR) ASSERT(false);

while (1){ /*

wait for connection from clientestabilish communication with clientsock = …

*/pid_t pid;pid = fork();if (pid < 0)

ASSERT(false)else if (pid > 0) {

close(sock);}else if (pid == 0){

/*perform data exchange based on sock descriptor*/ close(sock); return 0;}

}18

static void sigint_handler (int signo){ int status; while (waitpid(-1, &status, WNOHANG) > 0);}

IPC• shared memory• signals• pipes• named pipes• message queues• sockets• semaphores• files

19

Thread vs Processes

process• complex interprocesses

communications (latency, security problem)

• simple to create and manage

• more expensive (clear cache)

• need more memory• need more time to

switch contextArt of Multiprocessor

Programming20

Thread vs Processes

thread• simple interthread

communication• require

synchronisation• less expensive • faster to create

process• complex interprocesses

communications (latency, security problem)

• simple to create and manage

• more expensive (clear cache)

• need more memory• need more time to

switch contextArt of Multiprocessor

Programming21

Pthread API

• thread management• thread atributess• synchronisation

22

Creating threadNAME

pthread_create - creates a new thread, with attributes specified by attr 

SYNOPSIS#include <pthread.h>

int pthread_create(

pthread_t *thread,

const pthread_attr_t *attr,

void* (*start_routine)(void*),

void *arg); 23

pthread_create example

void *thread_fun(void *arg) {

if ((int)arg == 7)//do something

}

pthread_t tid;pthread_attr_t attr;

//attr initialisation...

if (pthread_create(&tid, &attr, thread_fun, (void*)7)ASSERT(false);

24

Exiting thread

NAMEpthread_exit - terminates the calling thread, returning status 

SYNOPSIS#include <pthread.h> void pthread_exit(void *status);

25

Additional functions

26

NAMEthread_self - returns the thread ID of the calling

thread.

SYNOPSIS#include <pthread.h>

pthread_t pthread_self(void);

NAME pthread_equal - compares the thread IDs t1 and t2

and returns a non-zero value if they are equal; otherwise, it returns zero.  

SYNOPSIS#include <pthread.h>

int pthread_equal(pthread_t t1, pthread_t t2);

Joining threadsvoid *thread_fun(void *arg) {

//do something pthread_exit(NULL);

}

int main(){

pthread_t tid;void* status;

if (pthread_create(&tid, NULL, thread_fun, NULL)ASSERT(false);

//do something

return 0;}

27

Joining threadsvoid *thread_fun(void *arg) {

//do something pthread_exit(NULL);

}

int main(){

pthread_t tid;void* status;

if (pthread_create(&tid, NULL, thread_fun, NULL)ASSERT(false);

//do something

if (pthread_join(main_thr, &status))ASSERT(false);

return 0;}

28

Joining threads

NAMEpthread_join - blocks the calling thread until thread terminates. If status is not null, the status from pthread_exit() will be placed there.

SYNOPSIS#include <pthread.h> int pthread_join(pthread_t thread, void **status);

29

Joining threads

30

int main(){

pthread_t tid;void* status;

if (pthread_create(&tid, NULL, thread_fun, NULL)ASSERT(false);

//do something

if (pthread_join(main_thr, &status))ASSERT(false);

return 0;}

void *thread_fun(void *arg) {

//do something pthread_exit(NULL);

}

What, if we don’t want to wait for thread

pthread_attr_t attr;

if (pthread_attr_init(&attr)) ASSERT(false);

if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))ASSERT(false);

/*create new thread*/

if (pthread_attr_destroy(&attr)) ASSERT(false);

31

What, if we don’t want to wait for thread

32

NAMEpthread_detach- turns the current thread into a detached thread.

SYNOPSIS#include <pthread.h> int pthread_detach(pthread_t thread);

Threads attributes

All threads attributes are set in a thread attributes object by a function of the form:

int pthread_attr_setname( pthread_attr_t *attr, Type t);

All threads attributes are retrieved from a threads attributes object by a function of the form:

int pthread_attr_getname( pthread_attr_t *attr, Type t);

33

Threads attributes

All threads attributes are set in a thread attributes object by a function of the form:

int pthread_attr_setname( pthread_attr_t *attr, Type t);

All threads attributes are retrieved from a threads attributes object by a function of the form:

int pthread_attr_getname( pthread_attr_t *attr, Type t);

34

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);

Threads attributesNAME TYPE DESCRIPTION

stacksize size_t The thread's stack size.

stackaddr void* The thread's stack address.

guardsize size_t The thread's stack guard size.

detachstate int The thread's detach state.

contentionscope int The thread’s scope

inheritsched int The thread’s scheduling inheritence

schedpolicy int The thread’s scheduling polices

schedparam struct sched_param The thread’s scheduling parameters 35

Threads attributesNAME TYPE DESCRIPTION

stacksize size_t The thread's stack size.

stackaddr void* The thread's stack address.

guardsize size_t The thread's stack guard size.

detachstate int The thread's detach state.

contentionscope int The thread’s scope

inheritsched int The thread’s scheduling inheritence

schedpolicy int The thread’s scheduling polices

schedparam struct sched_param The thread’s scheduling parameters 36

The stacksize attribute shall define the minimum stack size (in bytes) allocated for the created threads stack.

Threads attributesNAME TYPE DESCRIPTION

stacksize size_t The thread's stack size.

stackaddr void* The thread's stack address.

guardsize size_t The thread's stack guard size.

detachstate int The thread's detach state.

contentionscope int The thread’s scope

inheritsched int The thread’s scheduling inheritence

schedpolicy int The thread’s scheduling polices

schedparam struct sched_param The thread’s scheduling parameters 37

The stackaddr attribute specifies the location of storage to be used for the created thread's stack.

Threads attributesNAME TYPE DESCRIPTION

stacksize size_t The thread's stack size.

stackaddr void* The thread's stack address.

guardsize size_t The thread's stack guard size.

detachstate int The thread's detach state.

contentionscope int The thread’s scope

inheritsched int The thread’s scheduling inheritence

schedpolicy int The thread’s scheduling polices

schedparam struct sched_param The thread’s scheduling parameters 38

The guardsize attribute controls the size of the guard area for the created thread's stack. The guardsize attribute provides protection against overflow of the stack pointer. If a thread's stack is created with guard protection, the implementation allocates extra memory at the overflow end of the stack as a buffer against stack overflow of the stack pointer.

Threads attributesNAME TYPE DESCRIPTION

stacksize size_t The thread's stack size.

stackaddr void* The thread's stack address.

guardsize size_t The thread's stack guard size.

detachstate int The thread's detach state.

contentionscope int The thread’s scope

inheritsched int The thread’s scheduling inheritence

schedpolicy int The thread’s scheduling polices

schedparam struct sched_param The thread’s scheduling parameters 39

Control whether the thread is created in the joinable state (PTHREAD_CREATE_JOINABLE) or in the detached state ( PTHREAD_CREATE_DETACHED).

Threads attributesNAME TYPE DESCRIPTION

stacksize size_t The thread's stack size.

stackaddr void* The thread's stack address.

guardsize size_t The thread's stack guard size.

detachstate int The thread's detach state.

contentionscope int The thread’s scope

inheritsched int The thread’s scheduling inheritence

schedpolicy int The thread’s scheduling polices

schedparam struct sched_param The thread’s scheduling parameters 40

The contentionscope attribute may have the values PTHREAD_SCOPE_SYSTEM, signifying system scheduling contention scope, or PTHREAD_SCOPE_PROCESS, signifying process scheduling contention scope.

Threads attributesNAME TYPE DESCRIPTION

stacksize size_t The thread's stack size.

stackaddr void* The thread's stack address.

guardsize size_t The thread's stack guard size.

detachstate int The thread's detach state.

contentionscope int The thread’s scope

inheritsched int The thread’s scheduling inheritence

schedpolicy int The thread’s scheduling polices

schedparam struct sched_param The thread’s scheduling parameters 41

When the attributes objects are used by pthread_create(), the inheritsched attribute determines how the other scheduling attributes of the created thread shall be set. •PTHREAD_INHERIT_SCHED Specifies that the thread scheduling attributes shall be inherited from the creating thread, and the scheduling attributes in this attr argument shall be ignored. •PTHREAD_EXPLICIT_SCHED Specifies that the thread scheduling attributes shall be set to the corresponding values from this attributes object.

Threads attributesNAME TYPE DESCRIPTION

stacksize size_t The thread's stack size.

stackaddr void* The thread's stack address.

guardsize size_t The thread's stack guard size.

detachstate int The thread's detach state.

contentionscope int The thread’s scope

inheritsched int The thread’s scheduling inheritence

schedpolicy int The thread’s scheduling polices

schedparam struct sched_param The thread’s scheduling parameters 42

The supported values of policy shall include SCHED_FIFO, SCHED_RR, and SCHED_OTHER,

Threads attributesNAME TYPE DESCRIPTION

stacksize size_t The thread's stack size.

stackaddr void* The thread's stack address.

guardsize size_t The thread's stack guard size.

detachstate int The thread's detach state.

contentionscope int The thread’s scope

inheritsched int The thread’s scheduling inheritence

schedpolicy int The thread’s scheduling polices

schedparam struct sched_param The thread’s scheduling parameters 43

For the SCHED_FIFO and SCHED_RR policies, the only required member of param is sched_priority. For the SCHED_SPORADIC policy, the required members of the param structure are sched_priority, sched_ss_low_priority, sched_ss_repl_period, sched_ss_init_budget, and sched_ss_max_repl. The specified sched_ss_repl_period must be greater than or equal to the specified sched_ss_init_budget for the function to succeed; if it is not, then the function shall fail. The value of sched_ss_max_repl shall be within the inclusive range [1, {SS_REPL_MAX}] for the function to succeed; if not, the function shall fail.

Threads attributesNAME TYPE DESCRIPTION

stacksize size_t The thread's stack size.

stackaddr void* The thread's stack address.

guardsize size_t The thread's stack guard size.

detachstate int The thread's detach state.

contentionscope int The thread’s scope

inheritsched int The thread’s scheduling inheritence

schedpolicy int The thread’s scheduling polices

schedparam struct sched_param The thread’s scheduling parameters 44

int pthread_setschedparam(pthread_t, int , const struct sched_param *);

int pthread_detach(pthread_t);

Threads attributesNAME

pthread_attr_destroy, pthread_attr_init - destroy and initialize the thread attributes object  

SYNOPSIS#include <pthread.h>

int pthread_attr_destroy(pthread_attr_t *attr);int pthread_attr_init(pthread_attr_t *attr);

45

Threads attributes - example

pthread_attr_t attr;size_t size = 1024;

if (pthread_attr_init(&attr)) ASSERT(false);

if (pthread_attr_getstacksize(&attr, &size))ASSERT(false);

/*create new thread*/

if (pthread_attr_destroy(&attr)) ASSERT(false);

46

Canceling threadsNAME

pthread_cancel - function requests that thread be cancelled.

SYNOPSIS#include <pthread.h>

int pthread_cancel(pthread_t thread);

47

Canceling threadsNAME

pthread_cleanup_push, pthread_cleanup_pop - pushes the handler routine and argument onto the calling thread’s cancellation cleanup stack or removes the routine at the top of the calling thread’s cancellation cleanup stack and invokes it if execute is non-zero.

SYNOPSIS#include <pthread.h>

void pthread_cleanup_push(void (*routine)(void *), void *arg); void pthread_cleanup_pop(int execute);

48

Canceling threadsNAME

pthread_cleanup_push, pthread_cleanup_pop - pushes the handler routine and argument onto the calling thread’s cancellation cleanup stack or removes the routine at the top of the calling thread’s cancellation cleanup stack and invokes it if execute is non-zero.

SYNOPSIS#include <pthread.h>

void pthread_cleanup_push(void (*routine)(void *), void *arg); void pthread_cleanup_pop(int execute);

49

Canceling threadsNAME

pthread_setcanceltype, pthread_setcancelstate - This function both sets the calling thread’s cancellability type/state to type/state and returns the previous value in oldtype/oldstate. Legal values for type are PTHREAD_CANCEL_DEFERRED and

PTHREAD_CANCEL_ASYNCHRONOUS. Legal values for state are PTHREAD_CANCEL_ENABLED and PTHREAD_CANCEL_DISABLED.

SYNOPSIS#include <pthread.h>

int pthread_setcanceltype(int type, int *oldtype);

int pthread_setcancelstate(int state, int *oldstate);

50

Canceling threadsNAME

pthread_testcancel - cancellation point. If the cancel state is disabled, it just returns. If there are no outstanding cancellation requests, then it will also return. Otherwise it will not return and the thread will be cancelled.

SYNOPSIS#include <pthread.h>

void pthread_testcancel(void);

51

Canceling threads - Examplevoid *thread_fun(void *arg)

{int *p;

pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);while (1){

p = malloc(10 * sizeof(int));

pthread_cleanup_push(cleanup_pointer, (void *) p);

//do somethingpthread_testcancel();//do somethingpthread_cleanup_pop(0);free(p);pthread_testcancel();

}pthread_exit(NULL);

}52

int main(){

pthread_t tid;void* status;

if (pthread_create(&tid, NULL, thread_fun, NULL)

ASSERT(false);//do somethingreturn 0;

}

void cleanup_pointer(void* p){

free(p);}

Canceling threads

53

Thread specific data (TSD)

• Sometimes it is useful to have data that is globally accessible to any function, yet still unique to the thread.

54

Thread specific data (TSD)

int pthread_key_create(pthread_key_t *, void (*)(void *));

int pthread_key_delete(pthread_key_t);

int pthread_setspecific(pthread_key_t, const void *);

void *pthread_getspecific(pthread_key_t);

55

Thread specific data example

pthread_key_t house_key;void foo(void * arg){

pthread_setspecific(house_key, arg);bar();

}void bar(){

float n;n = (float) pthread_getspecific(house_key);

}int main(){...

pthread_keycreate(&house_key, destroyer);pthread_create(&tid, NULL, foo, (void *) 1.414);pthread_create(&tid, NULL, foo, (void *) 3.141592653589);

...} 56

Synchronisation

• Mutexes• Semaphores• Condition Variables

57

Mutex

The mutual exclusion lock is the simplest and most primitive synchronization variable. It provides a single, absolute owner for the section of code (thus a critical section) that it brackets between the calls to pthread_mutex_lock()and pthread_mutex_unlock(). The first thread that locks the mutex gets ownership, and any subsequent attempts to lock it will fail, causing the calling thread to go to sleep.

58

Mutex initialisationNAME

pthread_mutex_init, pthread_mutex_destroy - initializes mutex with attr or destroys the mutex, making it unusable in any form

SYNOPSIS#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); int pthread_mutex_destroy(pthread_mutex_t *mutex); 59

Mutex unlock operationNAME

pthread_mutex_unlock - unlocks mutex and wakes up the first thread sleeping on it.

SYNOPSIS#include <pthread.h>

int pthread_mutex_unlock(pthread_mutex_t *mutex);

60

Mutex example

thread 1add(request_t *request){

pthread_mutex_lock(&lock);request->next = requests; requests = request pthread_mutex_unlock(&lock);

}

thread 2

request_t *remove(){ pthread_mutex_lock(&lock);

...sleeping...

request = requests;requests = requests->next;pthread_mutex_unlock(&lock)return(request);

}

61

Mutex example

62

Semaphores

A counting semaphore6 is a variable that you can increment arbitrarily high, but decrement only to zero. A sem_post() operation increments the semaphore, while a sem_wait() attempts to decrement it. If the semaphore is greater than zero, the operation succeeds; if not, then the calling thread must go to sleep until a different thread increments it.

63

Semaphores initialisationNAME

sem_init, sem_destroy - initializes the semaphore to value. If pshared is non-zero, then the semaphore will be sharable among processes. This destroys the semaphore.

SYNOPSIS#include <pthread.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);int sem_destroy(sem_t *sem);

64

Semaphores operationsNAME

sem_post, sem_wait, sem_trywait - function increments the value of the semaphore or decrements the value of sem by one. If the semaphore’s value is zero, sem_wait() blocks, waiting for the semaphore to be incremented by another process or thread, while sem_trywait() will return immediately.

SYNOPSIS#include <pthread.h>

int sem_post(sem_t *sem);int sem_trywait(sem_t *sem);int sem_wait(sem_t *sem); 65

Semaphores operations

66

Semaphores operationsNAME

sem_open, sem_close - returns a pointer to the semaphore name. All processes which call this on the same name will get the same semaphore pointer or closes the named semaphore for this process.

SYNOPSIS#include <pthread.h>

sem_t *sem_open(char *name, int oflag,... );int sem_close(sem_t *sem);

67

Semaphors example

68

Semaphors example

69

producer(){ request_t *request; while(1) { request = get_request(); add(request); sem_post(&requests_length); }}

consumer(){ request_t *request; while(1){ SEM_WAIT(&requests_length);

request = remove();process_request(request);

}}

request_t *get_request(){ request_t *request; request = (request_t *) malloc(sizeof(request_t)); request->data = read_from_net(); return(request)}

void process_request(request_t *request){ process(request->data); free(request);}

Conditional Variables

70

Conditional Variable initialisation

NAMEpthread_cond_init, pthread_cond_destroy - initializes cond with att or destroys the condition variable, making it unusable in any form.

SYNOPSIS#include <pthread.h>

int pthread_cond_init(pthread_cond_t *cond, constpthread_condattr_t *attr); int pthread_cond_destroy(pthread_cond_t *cond);

71

Conditional Variable Wait Operation

NAMEpthread_cond_wait, pthread_cond_timewait - atomically releases mutex and causes the calling thread to block on cond. Upon successful return, the mutex will be reacquired.

SYNOPSIS#include <pthread.h>

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t*mutex);int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex, const struct timespec *abstime);

72

Conditional Variable Signal Operation

NAMEpthread_cond_signal, pthread_cond_broadcast - unblocks the first thread (if any) blocked on a condition variable or unblocks all threads blocked on a condition variable. You do notknow the order in which they awake.

SYNOPSIS#include <pthread.h>

int pthread_cond_signal(pthread_cond_t *cond);int pthread_cond_broadcast(pthread_cond_t *cond);

73

Conditional Variable Example

thread 1pthread_mutex_lock(&m);while (!my_condition) pthread_cond_wait(&c,

&m);

... sleeping ...

do_thing()pthread_mutex_unlock(&m);

thread 2

pthread_mutex_lock(&m);my_condition = TRUE;pthread_mutex_unlock(&m);pthread_cond_signal(&c);

74

Conditional Variable Example

75

Conditional Variable Example

void *producer(void *arg){ request_t *request; while(1) {

request = get_request();pthread_mutex_lock(&r_lock);while (length >= 10)

pthread_cond_wait(&r_producer, &r_lock); add(request); length++;

pthread_mutex_unlock(&r_lock); pthread_cond_signal(&r_consumer); }}

void *consumer(void *arg){ request_t *request; while(1) { pthread_mutex_lock(&r_lock); while (length == 0) pthread_cond_wait(&r_consumer, &r_lock); request = remove(); length--; pthread_mutex_unlock(&r_lock); pthread_cond_signal(&r_producer); process_request(request); }}

76

Multithread API’sWindows OS

77

78

79

Thank You

80