Title: Multithread API
1Multithread APIs
- Adam Piotrowski
- Grzegorz Jablonski
Lecture III
2Agenda
- Signals software asynchronous interrupts
- Processes
- Threads
3Signals
- 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
4Type 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
5Signal handling
- NAME
- signal - simplified software signal facilities Â
- SYNOPSIS
- include ltsignal.hgt
- void ( signal(int sig, void func)(int)))(int)
-
- typedef void (sig_t) (int)
- sig_t signal(int sig, sig_t func)
6Signals - 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
7Processes
- Processes are object code in execution active,
alive, running programs. - Processes consist of data, resources, state, and
a virtualized computer.
8Multi processes application
parent process
fork
fork
fork
fork
child process
child process
child process
child process
9fork
- NAME
- fork -- create a new process
- SYNOPSIS
- include ltsys/types.hgt include ltunistd.hgt
- pid_t fork(void)
10fork example
- pid_t pid
- pid fork()
- if (pid lt 0)
- ASSERT(false)
- else if (pid gt 0)
- printf( Parent process)
-
- else if (pid 0)
- printf(Child process)
-
-
- variables are duplicated
- descriptors are duplicated, too
11fork example
- pid_t pid
- pid fork()
- if (pid lt 0)
- ASSERT(false)
- else if (pid gt 0)
- printf( Parent process)
-
- else if (pid 0)
- printf(Child process)
-
-
- pid_t pid
- pid fork()
- if (pid lt 0)
- ASSERT(false)
- else if (pid gt 0)
- printf( Parent process)
-
- else if (pid 0)
- printf(Child process)
-
-
12fork example
- int sock
- while (1)
- /
- wait for connection from client
- estabilish communication with client
- sock
- /
- pid_t pid
- pid fork()
- if (pid lt 0)
- ASSERT(false)
- else if (pid gt 0)
- close(sock)
-
- else if (pid 0)
- /perform data exchange based on sock
descriptor/ - close(sock)
- return 0
-
13Copy-on-Write
14processes SIGCHLD signal
15processes SIGCHLD signal
- int sock
-
- while (1)
- /
- wait for connection from client
- estabilish communication with client
- sock
- /
- pid_t pid
- pid fork()
- if (pid lt 0)
- ASSERT(false)
- else if (pid gt 0)
- close(sock)
-
- else if (pid 0)
- /perform data exchange based on sock
descriptor/ - close(sock)
16processes 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 lt 0)
- ASSERT(false)
- else if (pid gt 0)
- close(sock)
-
- else if (pid 0)
- /perform data exchange based on sock
descriptor/ - close(sock)
17processes 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 lt 0)
- ASSERT(false)
- else if (pid gt 0)
- close(sock)
-
- else if (pid 0)
- /perform data exchange based on sock
descriptor/ - close(sock)
static void sigint_handler (int signo) int
status wait(status)
18processes 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 lt 0)
- ASSERT(false)
- else if (pid gt 0)
- close(sock)
-
- else if (pid 0)
- /perform data exchange based on sock
descriptor/ - close(sock)
static void sigint_handler (int signo) int
status while (waitpid(-1, status, WNOHANG) gt
0)
19IPC
- shared memory
- signals
- pipes
- named pipes
- message queues
- sockets
- semaphores
- files
20Thread vs Processes
- complex interprocesses communications (latency,
security problem) - simple to create and manage
- more expensive (clear cache)
- need more memory
- need more time to switch context
21Thread vs Processes
- simple interthread communication
- require synchronisation
- less expensive
- faster to create
- complex interprocesses communications (latency,
security problem) - simple to create and manage
- more expensive (clear cache)
- need more memory
- need more time to switch context
22Pthread API
- thread management
- thread atributess
- synchronisation
23Creating thread
- NAME
- pthread_create - creates a new thread, with
attributes specified by attr - SYNOPSIS
- include ltpthread.hgt
- int pthread_create(
- pthread_t thread,
- const pthread_attr_t attr,
- void (start_routine)(void),
- void arg)
24pthread_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)
25Exiting thread
- NAME
- pthread_exit - terminates the calling thread,
returning status - SYNOPSIS
- include ltpthread.hgt
- void pthread_exit(void status)
26Additional functions
NAME thread_self - returns the thread ID of the
calling thread. SYNOPSIS include ltpthread.hgt
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 ltpthread.hgt int
pthread_equal(pthread_t t1, pthread_t t2)
27Joining threads
- void 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
28Joining threads
- void 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
29Joining 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 ltpthread.hgt
- int pthread_join(pthread_t thread, void
status)
30Joining threads
- 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)
31What, if we dont 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)
32What, if we dont want to wait for thread
- NAME
- pthread_detach- turns the current thread into a
detached thread. - SYNOPSIS
- include ltpthread.hgt
- int pthread_detach(pthread_t thread)
33Threads 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)
34Threads 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)
int pthread_attr_setdetachstate(pthread_attr_t
attr, int detachstate)
int pthread_attr_getdetachstate(const
pthread_attr_t attr, int detachstate)
35Threads attributes
NAME 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 threads scope
inheritsched int The threads scheduling inheritence
schedpolicy int The threads scheduling polices
schedparam struct sched_param The threads scheduling parameters
36Threads attributes
NAME 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 threads scope
inheritsched int The threads scheduling inheritence
schedpolicy int The threads scheduling polices
schedparam struct sched_param The threads scheduling parameters
The stacksize attribute shall define the minimum
stack size (in bytes) allocated for the created
threads stack.
37Threads attributes
NAME 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 threads scope
inheritsched int The threads scheduling inheritence
schedpolicy int The threads scheduling polices
schedparam struct sched_param The threads scheduling parameters
The stackaddr attribute specifies the location of
storage to be used for the created thread's stack.
38Threads attributes
NAME 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 threads scope
inheritsched int The threads scheduling inheritence
schedpolicy int The threads scheduling polices
schedparam struct sched_param The threads scheduling parameters
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.
39Threads attributes
NAME 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 threads scope
inheritsched int The threads scheduling inheritence
schedpolicy int The threads scheduling polices
schedparam struct sched_param The threads scheduling parameters
Control whether the thread is created in the
joinable state (PTHREAD_CREATE_JOINABLE) or in
the detached state ( PTHREAD_CREATE_DETACHED).
40Threads attributes
NAME 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 threads scope
inheritsched int The threads scheduling inheritence
schedpolicy int The threads scheduling polices
schedparam struct sched_param The threads scheduling parameters
The contentionscope attribute may have the values
PTHREAD_SCOPE_SYSTEM, signifying system
scheduling contention scope, or
PTHREAD_SCOPE_PROCESS, signifying process
scheduling contention scope.
41Threads attributes
- 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.
NAME 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 threads scope
inheritsched int The threads scheduling inheritence
schedpolicy int The threads scheduling polices
schedparam struct sched_param The threads scheduling parameters
42Threads attributes
NAME 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 threads scope
inheritsched int The threads scheduling inheritence
schedpolicy int The threads scheduling polices
schedparam struct sched_param The threads scheduling parameters
The supported values of policy shall include
SCHED_FIFO, SCHED_RR, and SCHED_OTHER,
43Threads attributes
NAME 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 threads scope
inheritsched int The threads scheduling inheritence
schedpolicy int The threads scheduling polices
schedparam struct sched_param The threads scheduling parameters
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.
44Threads attributes
NAME 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 threads scope
inheritsched int The threads scheduling inheritence
schedpolicy int The threads scheduling polices
schedparam struct sched_param The threads scheduling parameters
int pthread_setschedparam(pthread_t, int , const
struct sched_param )
int pthread_detach(pthread_t)
45Threads attributes
- NAME
- pthread_attr_destroy, pthread_attr_init -
destroy and initialize the thread attributes
object  - SYNOPSIS
- include ltpthread.hgt
- int pthread_attr_destroy(pthread_attr_t
attr)int pthread_attr_init(pthread_attr_t
attr)
46Threads 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)
47Canceling threads
- NAME
- pthread_cancel - function requests that thread
be cancelled. - SYNOPSIS
- include ltpthread.hgt
- int pthread_cancel(pthread_t thread)
48Canceling threads
- NAME
- pthread_cleanup_push, pthread_cleanup_pop -
pushes the handler routine and argument onto the
calling threads cancellation cleanup stack or
removes the routine at the top of the calling
threads cancellation cleanup stack and invokes
it if execute is non-zero. - SYNOPSIS
- include ltpthread.hgt
- void pthread_cleanup_push(void (routine)(void
), void arg) void pthread_cleanup_pop(int
execute)
49Canceling threads
- NAME
- pthread_cleanup_push, pthread_cleanup_pop -
pushes the handler routine and argument onto the
calling threads cancellation cleanup stack or
removes the routine at the top of the calling
threads cancellation cleanup stack and invokes
it if execute is non-zero. - SYNOPSIS
- include ltpthread.hgt
- void pthread_cleanup_push(void (routine)(void
), void arg) void pthread_cleanup_pop(int
execute)
50Canceling threads
- NAME
- pthread_setcanceltype, pthread_setcancelstate -
This function both sets the calling threads
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 ltpthread.hgt
- int pthread_setcanceltype(int type, int
oldtype) - int pthread_setcancelstate(int state, int
oldstate)
51Canceling 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 ltpthread.hgt
- void pthread_testcancel(void)
52Canceling threads - Example
- void 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 something
- pthread_testcancel()
- //do something
- pthread_cleanup_pop(0)
- free(p)
- pthread_testcancel()
-
- pthread_exit(NULL)
int main() pthread_t tid void status if
(pthread_create(tid, NULL, thread_fun,
NULL) ASSERT(false) //do something return
0
void cleanup_pointer(void p) free(p)
53Canceling threads
54Thread specific data (TSD)
- Sometimes it is useful to have data that is
globally accessible to any function, yet still
unique to the thread.
55Thread 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)
56Thread 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) - ...
57Synchronisation
- Mutexes
- Semaphores
- Condition Variables
58Mutex
- 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.
59Mutex initialisation
- NAME
- pthread_mutex_init, pthread_mutex_destroy -
initializes mutex with attr or destroys the
mutex, making it unusable in any form - SYNOPSIS
- include ltpthread.hgt
- int pthread_mutex_init(pthread_mutex_t mutex,
const pthread_mutexattr_t attr) int
pthread_mutex_destroy(pthread_mutex_t mutex)
60Mutex unlock operation
- NAME
- pthread_mutex_unlock - unlocks mutex and wakes
up the first thread sleeping on it. - SYNOPSIS
- include ltpthread.hgt
- int pthread_mutex_unlock(pthread_mutex_t
mutex)
61Mutex example
- add(request_t request)
-
- pthread_mutex_lock(lock)
- request-gtnext requests requests request
pthread_mutex_unlock(lock)
- request_t remove()
- pthread_mutex_lock(lock)
- ...sleeping...
- request requests
- requests requests-gtnext
- pthread_mutex_unlock(lock)
- return(request)
62Mutex example
63Semaphores
- 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.
64Semaphores 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 ltpthread.hgt
- int sem_init(sem_t sem, int pshared, unsigned
int value)int sem_destroy(sem_t sem)
65Semaphores 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
semaphores 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 ltpthread.hgt
- int sem_post(sem_t sem)
- int sem_trywait(sem_t sem)
- int sem_wait(sem_t sem)
66Semaphores operations
67Semaphores 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 ltpthread.hgt
- sem_t sem_open(char name, int oflag,... )
- int sem_close(sem_t sem)
68Semaphors example
69Semaphors example
request_t get_request() request_t request
request (request_t ) malloc(sizeof(reque
st_t)) request-gtdata read_from_net()
return(request) void process_request(request_t
request) process(request-gtdata)
free(request)
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)
70Conditional Variables
71Conditional 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 ltpthread.hgt
- int pthread_cond_init(pthread_cond_t cond,
const - pthread_condattr_t attr) int
pthread_cond_destroy(pthread_cond_t cond)
72Conditional 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 ltpthread.hgt
- 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)
73Conditional 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 ltpthread.hgt
- int pthread_cond_signal(pthread_cond_t
cond)int pthread_cond_broadcast(pthread_cond_t
cond)
74Conditional Variable Example
- pthread_mutex_lock(m)
- while (!my_condition)
- pthread_cond_wait(c, m)
- ... sleeping ...
- do_thing()
- pthread_mutex_unlock(m)
- pthread_mutex_lock(m)
- my_condition TRUE
- pthread_mutex_unlock(m)
- pthread_cond_signal(c)
75Conditional Variable Example
76Conditional Variable Example
- void producer(void arg)
- request_t request
- while(1)
- request get_request()
- pthread_mutex_lock(r_lock)
- while (length gt 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)
-
77Multithread APIsWindows OS
78(No Transcript)
79(No Transcript)
80Thank You