Multithread API’s
-
Upload
risa-caldwell -
Category
Documents
-
view
40 -
download
5
description
Transcript of Multithread API’s
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