D02_PosixThreads

Download Report

Transcript D02_PosixThreads

POSIX Threads
Introduction to Operating Systems: Discussion Module 3
POSIX Threads
 The
POSIX standard describes general thread behavior,
and the functions which control threads

Individual operating systems are allowed some freedom in how
threads are implemented, and hence how they behave
 Some

POSIX thread (pthread) attributes include:
A thread may be detached
Only non-detached threads my be joined
 join is to wait as thread is to process


A thread has a priority for scheduling


Threads may use several scheduling methods, some of which use priority
A thread may have local or global scope of contention

That is, it may compete with all threads in the system for CPU time, or it
may compete only with threads in the same task (process)
The thread attribute object
 The
attributes of a thread are held in a thread
attribute object, which is a struct defined in
pthread.h.
 You can declare a pthread attribute in your code,
but it can only be initialized or modified by the
following functions:
int
int
int
int
pthread_attr_init(pthread_attr_t *attr);
pthread_attr_setstackaddr();
pthread_attr_setstacksize();
pthread_attr_setdetachstate();
The thread attribute object
a thread using a NULL attribute argument
has the same effect as using a default attribute:
 Creating
 Non-detached
(joinable)
 With a default stack and stack size
 With the parent’s priority
 To
create threads with other attributes, the
generating attribute object must be modified using
the pthread_attr_set functions
Create a pthread
pthread_create() to add a new thread of
control to the current process
 Use
Pthread_create
writes the thread
id in tid.
int pthread_create(
pthread_t *tid,
const pthread_attr_t *tattr,
void*(*start_routine)(void *),
void *arg);
Create a pthread
pthread_create() to add a new thread of
control to the current process.
 Use
The address of a
thread attribute
object is passed
using tattr
int pthread_create(
pthread_t *tid,
const pthread_attr_t *tattr,
void*(*start_routine)(void *),
void *arg);
Create a pthread
pthread_create() to add a new thread of
control to the current process.
 Use
The thread runs
a function
passed in
start_routine
int pthread_create(
pthread_t *tid,
const pthread_attr_t *tattr,
void*(*start_routine)(void *),
void *arg);
Create a pthread
pthread_create() to add a new thread of
control to the current process.
 Use
The start
routine’s
argument is
passed with arg
int pthread_create(
pthread_t *tid,
const pthread_attr_t *tattr,
void*(*start_routine)(void *),
void *arg);
Create a pthread
 When
start_routine returns, the thread exits with a
status equal to the value returned by start_routine
 The function start_routine should match the
signature
void* start_rountine(void*)
 The
argument passed to start_routine is a pointer to
a structure which contains the actual values needed
by start_routine
Create a pthread
function pthread_create() returns zero on
successful completion.
 The

Any other returned value indicates that an error occurred.
 When
any of the following conditions are detected,
pthread_create() fails and returns the
corresponding constant value

EAGAIN


A system limit is exceeded, such as when too many threads have been
created.
EINVAL

The attribute pointer, tattr, doesn’t refer to a valid pthread attribute object.
Waiting for pthreads
 Use
pthread_join() to wait for a thread to terminate
 Prototype:
int pthread_join(
thread_t tid,
void **status);
 The pthread_join() function blocks the calling
thread until the thread specified by tid terminates
 The specified thread must be
in the current process
 non-detached

Waiting for pthreads
 The
exit status of the thread specified by tid is
written to status when pthread_join()
returns successfully
 Multiple threads cannot wait for the same thread to
terminate
 If
they try, one thread returns successfully and the others
fail with an error of ESRCH
Efficient pthread use
 When
there is no reason to synchronize with the
termination of a particular thread, then that thread
should be detached
 Reserve non-detached threads for only those
situations that require them
 But pthreads are created non-detached by default
 How
can that be changed?
Detaching a pthread
 pthread_detach()
detaches a thread, making it
unjoinable
 Prototype:
int pthread_detach(thread_t tid);
 The ID for a detached thread can be reclaimed when the
thread terminates

 If
Non-detached thread IDs are not reclaimed when the thread
terminates; they are retained until another thread calls join on the
terminated thread
the thread tid has not terminated,
pthread_detach() does not cause it to terminate
 The effect of multiple pthread_detach() calls on the
same target thread is unspecified
Detaching a pthread
 pthread_detach()
returns a zero when it
completes successfully.
 Any
other returned value indicates that an error
occurred
 When
any of the following conditions
are detected, pthread_detach() fails and
returns the corresponding value.
 EINVAL
 tid
is not a valid thread
 ESRCH
 tid
is not a valid, undetached thread in the current process
Even pthreads ask “who am I?”
pthread_self() to get the ID of the
calling thread
 Prototype:
pthread_t pthread_self(void);
 Use
 Returns
the ID of the calling thread
Comparing pthreads





Use pthread_equal() to compare the thread identification
numbers of two threads
Prototype:
int pthread_equal(
pthread_t tid1,
pthread_t tid2);
Returns a non-zero value when tid1 and tid2 are equal; otherwise,
zero is returned
When either tid1 or tid2 is an invalid thread identification number,
the result is unpredictable
Ex:
if (tid != pthread_self() ) //improper comparison
if (!pthread_equal( tid, pthread_self())) //correct
Polite pthreads
sched_yield() to cause the current thread
to yield its execution in favor of another thread
with the same or greater priority.
 Prototype:
int sched_yield(void);
 Use
 Returns
zero after completing successfully
 Otherwise
-1 is returned
The end of a pthread
 Use
pthread_exit() to terminate a thread
 Prototype:
void pthread_exit(void *status);
 The pthread_exit() function ends the calling thread

All thread-specific data bindings are released
 If
the calling thread is not detached, then the thread’s ID
and the exit status specified by status are retained until the
thread is joined

Otherwise, status is ignored and the thread’s ID can be reclaimed
immediately
So how does it end?
 A thread
can terminate its execution in the following ways:
By returning from its first (outermost) procedure, the threads
start routine
 By calling pthread_exit(), supplying an exit status

 The
default behavior of a thread is to linger until some
other thread has acknowledged its demise by “joining”
with it
 The joining thread receives the exit status of the dying
thread and the dying thread vanishes
Finishing Up
important special case arises when the initial thread —
the one calling main() — returns from main() or
calls exit()
 An
 This
action causes the entire process to terminate, along
with all its threads. So take care to ensure that the initial
thread does not return from main() prematurely!
 Note
that when the main thread merely calls
pthread_exit(), it stops only itself—the other threads
in the process, as well as the process, continue to exist

The process terminates when all its threads terminate
Solaris pthread attribute defaults
Value
Result
scope
PTHREAD_SCOPE_PROCESS
New thread is unbound – not permanently attached to LWP.
detachstate
PTHREAD_CREATE_JOINABLE
Exit status and thread are preserved after the thread terminates.
stackaddr
NULL
New thread has system-allocated stack address.
stacksize
1 megabyte
New thread has system-defined stack size.
Attribute
priority
New thread inherits parent thread priority.
inheritsched
PTHREAD_INHERIT_SCHED
New thread inherits parent thread scheduling priority.
schedpolicy
SCHED_OTHER
New thread uses Solaris-defined fixed priority scheduling;
threads run until preempted by a higher-priority thread or until
they block or yield.
A pthread state diagram
Joinable
pthread_create
pthread_exit
Dead joinable
New
pthread_detach
join
pthread_create
Detached
pthread_exit
Terminated
Compiling multithreaded code
 In
Solaris, you must invoke the compiler with the
following command line arguments to use pthreads
 –lpthread
 This
links the pthread library
 –lposix4
 This
links the posix library; it is needed for sched_yield