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