thr_create(3thread) thr_create(3thread)
NAME
thr_create - create a thread
SYNOPSIS
cc [options] -Kthread file
#include <thread.h>
int thr_create(void *stack_address, size_t stack_size,
void *(*start_routine)(void *arg), void *arg,
long flags, thread_t *new_thread);
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 pointer to 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
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 flags Parameter below).
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).
Copyright 1994 Novell, Inc. Page 1
thr_create(3thread) thr_create(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 may 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 a pointer to the argument to start_routine.
flags Parameter
flags specifies attributes for the new thread. It may 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 if the
Copyright 1994 Novell, Inc. Page 2
thr_create(3thread) thr_create(3thread)
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 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 when the last thread has
terminated. The process will terminate when
the last non-daemon thread terminates. Such
``helper threads'' may 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 only valid 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:
Copyright 1994 Novell, Inc. Page 3
thr_create(3thread) thr_create(3thread)
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 are 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.
Copyright 1994 Novell, Inc. Page 4
thr_create(3thread) thr_create(3thread)
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 is 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 via 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.
void *
t_main(void *arg)
{
...
}
int error;
void *t_arg = NULL;
thread_t t1_id;
error = thr_create((void*)NULL, 0, t_main, t_arg, 0, &t1_id);
Copyright 1994 Novell, Inc. Page 5
thr_create(3thread) thr_create(3thread)
The following example creates a multiplexed thread that will
use a user-allocated stack.
void *
t_main(void *arg)
{
...
}
int error;
void *t1_stack;
void *t_arg = NULL;
size_t t_size = 8192;
thread_t t1_id;
t1_stack = malloc(t_size);
error = thr_create(t1_stack, t_size, t_main, t_arg, 0, &t1_id);
The following example creates a daemon thread that will use a
minimally-sized stack allocated by the library:
void *
t_main(void *arg)
{
...
}
int error;
void *t1_stack;
void *t_arg = NULL;
thread_t t1_id;
error = thr_create((void*)NULL, (size_t)thr_minstack(), t_main,
t_arg, THR_DAEMON, &t1_id);
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.
void *
t_main(void *arg)
{
...
}
int error;
Copyright 1994 Novell, Inc. Page 6
thr_create(3thread) thr_create(3thread)
void *t1_stack;
void *t_arg = NULL;
thread_t t1_id;
sched_param_t sched_param;
error = thr_create((void*)NULL, 0, t_main, t_arg,
THR_SUSPENDED|THR_BOUND, &t1_id);
/* initialize sched_param to the SCHED_FIFO policy with priority 62 */
sched_param.policy = SCHED_FIFO;
((struct fifo_param *) sched_param.policy_params)->prio = 62;
error = thr_setscheduler(t1_id, &sched_param);
error = thr_continue(t1_id);
REFERENCES
fork(2), thr_continue(3thread), thr_exit(3thread),
thr_getconcurrency(3thread), thr_join(3thread),
thr_minstack(3thread), thr_self(3thread),
thr_setconcurrency(3thread), thr_setscheduler(3thread),
thr_suspend(3thread), thread(3thread)
Copyright 1994 Novell, Inc. Page 7