int thr_create(void *stack_address, size_t stack_size,
void *(*start_routine)(void *), void *arg,
long flags, thread_t *new_thread);
Description
thr_create creates a new thread in the current process.
The new thread will execute the function specified by start_routine
with the argument specified by arg.
The new thread will be immediately runnable,
unless it is created with the THR_SUSPENDED flag
(see the description of the flags
parameter).
Parameters
stack_address
pointer to the base address for the new thread's stack
stack_size
size of the new thread's stack
start_routine
pointer to the function the new thread will execute
arg
the argument to start_routine
flags
attributes for the new thread
new_thread
pointer to the identifier for the new thread, set by thr_create
stack_address and stack_size parameters
The new thread will run on the stack described by
stack_address and stack_size.
The stack can be explicitly allocated by the user
or allocated automatically.
For an explicitly allocated stack:
Set stack_address to point to the user-allocated stack.
stack_address is the base, or lowest, address.
Set stack_size to the size in bytes of the user-allocated stack.
stack_size must be larger than the value
returned by
thr_minstack(3thread).
For an automatically allocated stack:
Set stack_address to NULL.
To get a default size stack, set stack_size to zero.
In this implementation, the default stack size is either
twice the page size or 16K bytes, whichever is greater.
To get a stack of a particular size,
set stack_size to the number of bytes you want.
stack_size must be larger than the value
returned by
thr_minstack(3thread).
Note that the stack can be silently shrunken
so the low and high addresses are properly aligned.
This implementation provides basic stack overflow detection
for stacks allocated by the library.
If a thread overflows its stack
a SIGSEGV signal will be generated.
start_routine parameter
start_routine points to the function that the new thread will
execute.
A return from start_routine has the same effect as
an explicit
thr_exit(3thread)
by the new thread
with status equal to the function return value.
The status or return value of a thread can be retrieved with
thr_join(3thread).
arg parameter
arg is the argument to start_routine.
flags parameter
flags specifies attributes for the new thread.
It can be 0 or constructed from the bitwise inclusive OR
of any of the following:
THR_SUSPENDED
Create the new thread in the suspended state.
This permits modification of scheduling parameters and other attributes
before the new thread executes start_routine.
The creating thread or another thread must call thr_continue
for the new thread to begin executing.
THR_BOUND
Bind the new thread to a new lightweight process (LWP)
created for the purpose, regardless of other flags.
The thread will not be scheduled on other LWPs even though the implementation
supports multiplexing of threads across LWPs.
THR_DETACHED
Create the new thread in the detached state.
The new thread cannot be awaited with
thr_join(3thread).
This gives a hint to the implementation that immediate reuse of
the new thread's resources on thr_exit is acceptable to the user.
The exit status of a detached thread cannot be retrieved.
THR_INCR_CONC
Increase the concurrency level as returned by
thr_getconcurrency(3thread)
by creating a new LWP in the pool, regardless of other flags.
THR_DAEMON
Create the new thread as a daemon thread.
The new thread will not be counted when determining
if the last thread has terminated.
The process will terminate when the last non-daemon thread terminates.
Such ``helper threads'' can be created for asynchronous I/O
or other activities, but do not prolong the life of the process when
there are no real application threads remaining.
If both THR_BOUND and THR_INCR_CONC are set,
two new LWPs are created:
one to which the new thread will be bound
and one to increase the pool.
new_thread parameter
If new_thread is not NULL, thr_create sets the
location pointed to by new_thread to the identifier for the
created thread.
The thread ID is valid only within the calling process.
Signal mask and scheduling characteristics
The newly created thread inherits the creating thread's signal mask,
as established by
thr_sigsetmask(3thread),
but without any pending signals.
The following table shows how priority and scheduling class
of a new thread are determined in this implementation.
Note that there are two levels of scheduling,
each with its own set of scheduling characteristics:
scheduling of LWPs on processors
scheduling of threads on LWPs
Bound threads are influenced exclusively by LWP scheduling
(system scheduling).
The scheduling of multiplexed threads
is primarily influenced by thread-level scheduling,
although it is affected by both levels.
New Bound Thread
New Multiplexed Thread
LWP sched class:
from creator
LWP sched class:
from pool
Bound
LWP priority:
from creator
LWP priority:
from pool
Creator
Thread sched class:
not used
Thread sched class:
SCHED_TS
Thread priority:
not used
Thread priority:
default (63)
LWP sched class:
from creator
LWP sched class:
from pool
Multiplexed
LWP priority:
from creator
LWP priority:
from pool
Creator
Thread sched class:
not used
Thread sched class:
SCHED_TS
Thread priority:
not used
Thread priority:
from creator
In this implementation, a multiplexed thread is always created
with the default scheduling class (SCHED_TS),
but its priority depends on whether the creating thread is bound
or multiplexed.
If the creating thread is multiplexed,
then a multiplexed thread inherits the priority of the creating thread.
If the creating thread is bound,
then a multiplexed thread is given the default priority of 63.
The Threads Library maintains a pool of LWPs for multiplexing
threads to run on.
The LWPs in the pool all have the same scheduling characteristics.
A bound thread inherits its scheduling class and priority from
the creating thread.
A bound thread is scheduled by the system,
therefore the scheduling class and priority it inherits
are those of the creating thread's LWP.
Security restrictions
thr_create requires no special permissions or privilege.
Return values
thr_create returns zero for success
and an error number for failure, as described below.
Errors
If any of the following conditions occurs,
thr_create returns the corresponding value:
ENOMEM
Insufficient memory to complete thr_create.
EINVAL
stack_size is zero and stack_address is not NULL.
EINVAL
stack_size, after shrinking to aligned offsets,
is smaller than an implementation-defined lower bound
as returned by thr_minstack.
EINVAL
start_routine is NULL.
If any of the following conditions are detected,
thr_create returns the corresponding value:
EAGAIN
A resource limit would be exceeded if the call succeeded.
Note that EAGAIN cannot always be detected.
EINVAL
The process is being traced using ptrace.
Usage
Examples
The following example creates a multiplexed thread
that will use a library-allocated stack.
Note that using 0 as the flags argument
will create a thread that is multiplexed (not bound) and can be awaited
with thr_join.
The library will allocate a default size stack
because stack_address is NULL and stack_size is 0.
The following example creates a suspended, bound thread,
then modifies its scheduling parameters before continuing.
See
thr_setscheduler(3thread)
for more details
about modifying thread scheduling parameters.
The library will allocate a default size stack
because stack_address is NULL and stack_size is 0.