Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "Multithread API’s Adam Piotrowski Grzegorz Jabłoński Lecture III."— Presentation transcript:

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

2 Agenda Signals – software asynchronous interrupts Processes Threads 2

3 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

4 Type of signals SignalNameDescription SIGCHLDChild has terminatedIgnored SIGINTUser generated the interrupt character (Ctrl-C) Terminate SIGALRMSent by alarm()Terminate SIGUSR1Process-defined signalTerminate SIGKILLUncatchable process terminationTerminate SIGPIPEProcess wrote to a pipe but there are no readers Terminate SIGABRTSent by abort()Terminate with core dump SIGSEGVMemory access violationTerminate with core dump 4

5 Signal handling NAME signal - simplified software signal facilities SYNOPSIS #include void (* signal(int sig, void *func)(int)))(int); typedef void (*sig_t) (int); sig_t signal(int sig, sig_t func); 5

6 Signals - Example static 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

7 Processes Processes are object code in execution: active, alive, running programs. Processes consist of data, resources, state, and a virtualized computer. 7

8 Multi processes application 8 parent process child process fork

9 NAME fork -- create a new process SYNOPSIS #include #include pid_t fork(void); 9

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”); } variables are duplicated descriptors are duplicated, too 10

11 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”); }

12 fork example int sock; while (1){ /* wait for connection from client estabilish communication with client sock = … */ 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

13 Copy-on-Write 13

14 processes & SIGCHLD signal 14

15 processes & SIGCHLD signal int sock; while (1){ /* wait for connection from client estabilish communication with client sock = … */ 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

16 processes & SIGCHLD signal int sock; if (signal (SIGCHLD, sigint_handler) == SIG_ERR) ASSERT(false); while (1){ /* wait for connection from client estabilish communication with client sock = … */ 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

17 processes & SIGCHLD signal int sock; if (signal (SIGCHLD, sigint_handler) == SIG_ERR) ASSERT(false); while (1){ /* wait for connection from client estabilish communication with client sock = … */ 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); }

18 processes & SIGCHLD signal int sock; if (signal (SIGCHLD, sigint_handler) == SIG_ERR) ASSERT(false); while (1){ /* wait for connection from client estabilish communication with client sock = … */ 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); }

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

20 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 context Art of Multiprocessor Programming 20

21 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 context Art of Multiprocessor Programming 21

22 Pthread API thread management thread atributess synchronisation 22

23 Creating thread NAME pthread_create - creates a new thread, with attributes specified by attr SYNOPSIS #include int pthread_create( pthread_t *thread, const pthread_attr_t *attr, void* (*start_routine)(void*), void *arg); 23

24 pthread_create example void *thread_fun(void *arg) { if ((int)arg == 7) //do something } pthread_ttid; pthread_attr_t attr; //attr initialisation... if (pthread_create(&tid, &attr, thread_fun, (void*)7) ASSERT(false); 24

25 Exiting thread NAME pthread_exit - terminates the calling thread, returning status SYNOPSIS #include void pthread_exit(void *status); 25

26 Additional functions 26 NAME thread_self - returns the thread ID of the calling thread. SYNOPSIS #include 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 int pthread_equal(pthread_t t1, pthread_t t2);

27 Joining threads void *thread_fun(void *arg) { //do something pthread_exit(NULL); } int main() { pthread_ttid; void*status; if (pthread_create(&tid, NULL, thread_fun, NULL) ASSERT(false); //do something return 0; } 27

28 Joining threads void *thread_fun(void *arg) { //do something pthread_exit(NULL); } int main() { pthread_ttid; 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

29 Joining threads NAME pthread_join - blocks the calling thread until thread terminates. If status is not null, the status from pthread_exit() will be placed there. SYNOPSIS #include int pthread_join(pthread_t thread, void **status); 29

30 Joining threads 30 int main() { pthread_ttid; 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); }

31 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

32 What, if we don’t want to wait for thread 32 NAME pthread_detach- turns the current thread into a detached thread. SYNOPSIS #include int pthread_detach(pthread_t thread);

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); 33

34 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);

35 Threads attributes NAMETYPEDESCRIPTION stacksizesize_tThe thread's stack size. stackaddrvoid*The thread's stack address. guardsizesize_tThe thread's stack guard size. detachstateintThe thread's detach state. contentionscopeintThe thread’s scope inheritschedintThe thread’s scheduling inheritence schedpolicyintThe thread’s scheduling polices schedparamstruct sched_paramThe thread’s scheduling parameters 35

36 Threads attributes NAMETYPEDESCRIPTION stacksizesize_tThe thread's stack size. stackaddrvoid*The thread's stack address. guardsizesize_tThe thread's stack guard size. detachstateintThe thread's detach state. contentionscopeintThe thread’s scope inheritschedintThe thread’s scheduling inheritence schedpolicyintThe thread’s scheduling polices schedparamstruct sched_paramThe thread’s scheduling parameters 36 The stacksize attribute shall define the minimum stack size (in bytes) allocated for the created threads stack.

37 Threads attributes NAMETYPEDESCRIPTION stacksizesize_tThe thread's stack size. stackaddrvoid*The thread's stack address. guardsizesize_tThe thread's stack guard size. detachstateintThe thread's detach state. contentionscopeintThe thread’s scope inheritschedintThe thread’s scheduling inheritence schedpolicyintThe thread’s scheduling polices schedparamstruct sched_paramThe thread’s scheduling parameters 37 The stackaddr attribute specifies the location of storage to be used for the created thread's stack.

38 Threads attributes NAMETYPEDESCRIPTION stacksizesize_tThe thread's stack size. stackaddrvoid*The thread's stack address. guardsizesize_tThe thread's stack guard size. detachstateintThe thread's detach state. contentionscopeintThe thread’s scope inheritschedintThe thread’s scheduling inheritence schedpolicyintThe thread’s scheduling polices schedparamstruct sched_paramThe 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.

39 Threads attributes NAMETYPEDESCRIPTION stacksizesize_tThe thread's stack size. stackaddrvoid*The thread's stack address. guardsizesize_tThe thread's stack guard size. detachstateintThe thread's detach state. contentionscopeintThe thread’s scope inheritschedintThe thread’s scheduling inheritence schedpolicyintThe thread’s scheduling polices schedparamstruct sched_paramThe 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).

40 Threads attributes NAMETYPEDESCRIPTION stacksizesize_tThe thread's stack size. stackaddrvoid*The thread's stack address. guardsizesize_tThe thread's stack guard size. detachstateintThe thread's detach state. contentionscopeintThe thread’s scope inheritschedintThe thread’s scheduling inheritence schedpolicyintThe thread’s scheduling polices schedparamstruct sched_paramThe 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.

41 Threads attributes NAMETYPEDESCRIPTION stacksizesize_tThe thread's stack size. stackaddrvoid*The thread's stack address. guardsizesize_tThe thread's stack guard size. detachstateintThe thread's detach state. contentionscopeintThe thread’s scope inheritschedintThe thread’s scheduling inheritence schedpolicyintThe thread’s scheduling polices schedparamstruct sched_paramThe 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.

42 Threads attributes NAMETYPEDESCRIPTION stacksizesize_tThe thread's stack size. stackaddrvoid*The thread's stack address. guardsizesize_tThe thread's stack guard size. detachstateintThe thread's detach state. contentionscopeintThe thread’s scope inheritschedintThe thread’s scheduling inheritence schedpolicyintThe thread’s scheduling polices schedparamstruct sched_paramThe thread’s scheduling parameters 42 The supported values of policy shall include SCHED_FIFO, SCHED_RR, and SCHED_OTHER,

43 Threads attributes NAMETYPEDESCRIPTION stacksizesize_tThe thread's stack size. stackaddrvoid*The thread's stack address. guardsizesize_tThe thread's stack guard size. detachstateintThe thread's detach state. contentionscopeintThe thread’s scope inheritschedintThe thread’s scheduling inheritence schedpolicyintThe thread’s scheduling polices schedparamstruct sched_paramThe 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.

44 Threads attributes NAMETYPEDESCRIPTION stacksizesize_tThe thread's stack size. stackaddrvoid*The thread's stack address. guardsizesize_tThe thread's stack guard size. detachstateintThe thread's detach state. contentionscopeintThe thread’s scope inheritschedintThe thread’s scheduling inheritence schedpolicyintThe thread’s scheduling polices schedparamstruct sched_paramThe thread’s scheduling parameters 44 int pthread_setschedparam(pthread_t, int, const struct sched_param *); int pthread_detach(pthread_t);

45 Threads attributes NAME pthread_attr_destroy, pthread_attr_init - destroy and initialize the thread attributes object SYNOPSIS #include int pthread_attr_destroy(pthread_attr_t *attr); int pthread_attr_init(pthread_attr_t *attr); 45

46 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

47 Canceling threads NAME pthread_cancel - function requests that thread be cancelled. SYNOPSIS #include int pthread_cancel(pthread_t thread); 47

48 Canceling threads NAME 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 void pthread_cleanup_push(void (*routine)(void *), void *arg); void pthread_cleanup_pop(int execute); 48

49 Canceling threads NAME 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 void pthread_cleanup_push(void (*routine)(void *), void *arg); void pthread_cleanup_pop(int execute); 49

50 Canceling threads NAME 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 int pthread_setcanceltype(int type, int *oldtype); int pthread_setcancelstate(int state, int *oldstate); 50

51 Canceling threads NAME 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 void pthread_testcancel(void); 51

52 Canceling threads - Example void *thread_fun(void *arg) { int *p; pthread_setcanceltype(PTHREAD_CANC EL_DEFERRED, NULL); pthread_setcancelstate(PTHREAD_CANC EL_ENABLE, NULL); while (1){ p = malloc(10 * sizeof(int)); pthread_cleanup_push(cleanup_poi nter, (void *) p); //do something pthread_testcancel(); //do something pthread_cleanup_pop(0); free(p); pthread_testcancel(); } pthread_exit(NULL); } 52 int main() { pthread_ttid; void*status; if (pthread_create(&tid, NULL, thread_fun, NULL) ASSERT(false); //do something return 0; } void cleanup_pointer(void* p) { free(p); }

53 Canceling threads 53

54 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

55 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

56 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 *) );... } 56

57 Synchronisation Mutexes Semaphores Condition Variables 57

58 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

59 Mutex initialisation NAME pthread_mutex_init, pthread_mutex_destroy - initializes mutex with attr or destroys the mutex, making it unusable in any form SYNOPSIS #include int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); int pthread_mutex_destroy(pthread_mutex_t *mutex); 59

60 Mutex unlock operation NAME pthread_mutex_unlock - unlocks mutex and wakes up the first thread sleeping on it. SYNOPSIS #include int pthread_mutex_unlock(pthread_mutex_t *mutex); 60

61 Mutex example thread 1 add(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

62 Mutex example 62

63 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

64 Semaphores initialisation NAME 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 int sem_init(sem_t *sem, int pshared, unsigned int value); int sem_destroy(sem_t *sem); 64

65 Semaphores operations NAME 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 int sem_post(sem_t *sem); int sem_trywait(sem_t *sem); int sem_wait(sem_t *sem); 65

66 Semaphores operations 66

67 Semaphores operations NAME 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 sem_t *sem_open(char *name, int oflag,... ); int sem_close(sem_t *sem); 67

68 Semaphors example 68

69 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); }

70 Conditional Variables 70

71 Conditional Variable initialisation NAME pthread_cond_init, pthread_cond_destroy - initializes cond with att or destroys the condition variable, making it unusable in any form. SYNOPSIS #include int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_destroy(pthread_cond_t *cond); 71

72 Conditional Variable Wait Operation NAME pthread_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 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

73 Conditional Variable Signal Operation NAME pthread_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 not know the order in which they awake. SYNOPSIS #include int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond); 73

74 Conditional Variable Example thread 1 pthread_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

75 Conditional Variable Example 75

76 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

77 Multithread API’s Windows OS 77

78 78

79 79

80 Thank You 80


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

Similar presentations


Ads by Google