Creating a new thread
In SVR4.2MP and UnixWare 2.0 processes are single-threaded when they start running new programs
(that is, on entry to main,
following a successful call to
exec(2)).
The thread created to execute main
is known as the ``initial thread''.
If no additional threads are created, a process can continue
to execute with the same semantics as the traditional UNIX process.
New threads can be created via the
thr_create(3thread)
routine
int thr_create(
void *stack_address,
size_t stack_size,
void *(*start_routine)(void *arg),
void *arg,
long flags,
thread_t *new_thread
);
which takes the following parameters:
stack_address and stack_size-
These define the stack space for the new thread.
(This space is used for function call transactions
and for automatic variables in functions called by the thread.)
The stack of the traditional UNIX process has
``autogrow'' support by the operating system.
That is,
if the stack grows beyond its initial size the operating system
automatically increases its size as needed (or until it runs into
some other defined segment).
However,
threads (other than the initial thread)
use stacks that do not have autogrow support;
consequently,
the stacks should be allocated to meet the maximum needs of the thread.
As a convenience, the Threads Library will implicitly allocate a
reasonably-sized stack
(twice the page size or 16K bytes, whichever is greater)
if stack_address and stack_size
are set to NULL and 0, respectively,
-
The programmer can specify other sizes if needed.
The value must not be less than that returned by
thr_minstack(3thread).
Note that stack_address should point to the base address (lowest)
of the allocated space.
-
In this implementation,
the Threads Library manages the process address space so that
stack overflows will result in an addressing error (SIGSEGV).
For most applications, this is a desirable behavior.
It is better to discover such errors as soon as they occur rather than
have one stack corrupt another.
start_routine and arg-
These parameters define the starting condition of the newly created thread.
start_routine is
the function address where the new thread's execution will begin
and arg is the argument that start_routine will receive.
start_routine takes a single parameter of type (void *)
and returns a value of the same type.
These values can be used (with type casts) to pass values
(or aggregations of values in structures) of any type.
NOTE:
For portability,
do not cast an int to (void *),
and then cast it back to int.
These values should only be used as pointers;
otherwise, information can be lost.
Of course, a thread need not be entirely defined by a single function.
That initial function will typically call other functions.
flags-
These flags will be discussed as their respective topics arise
later in this section.
These flags are not mutually exclusive;
they can be combined with a bitwise inclusive OR.
For each flag, the relevant section is shown:
THR_SUSPENDED-
``Managing thread scheduling''
THR_BOUND-
``Managing threads concurrency''
THR_DETACHED-
``Waiting for thread termination''
THR_INCR_CONC-
``Managing threads concurrency''
THR_DAEMON-
``Terminating a thread''
new_thread-
The ``thread ID'' of the newly created thread is delivered
at this address.
-
This value can be used in other functions to influence that thread.
-
The scope of the value is limited to the enclosing process;
it is not relevant to threads in other processes.
-
A thread can learn its own thread ID number by the
thr_self(3thread)
function.
NOTE:
thr_create(3thread)
and most other functions in the Threads Library
return 0 on success.
On failure,
instead of setting the errno global variable,
they return the error code as the function's value.
The creation of one thread by another is conceptually similar
but not identical to
the creation of a new process by another process
via the
fork(2)
system call.
Some differences are:
-
After a
fork(2)
system call both the creator (parent) and created (child)
processes resume from the same point of computation
-- the return from
fork(2).
In contrast,
a new thread starts execution at the start_function
specified by the creator
(in some respects similar to the
exec(2)
system call),
while the creating thread returns from
thr_create(3thread).
-
The operating system maintains a
parent/child relationship between creating and created processes
that affects later interactions at process termination
(for example,
wait(2)
semantics).
In contrast, there is no innate hierarchy among threads.
Each is a ``sibling'' of the other.
Thus,
the creator might wait for the newly created thread to terminate or,
just as easily,
the new thread can wait for its creator to terminate.
{See discussion of
thr_join(3thread)
below.)
Next topic:
Terminating a thread
Previous topic:
Basic threads management
© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004