Threads and syncronization primitives
Provides cross-platform interface for threads handling and synchronization primitives.
Example of thread's function:
thread_result_t worker_thread(thread_arg_t arg) {
THREAD_ENTRY(arg, workload_t, wl);
...
if(cond)
THREAD_EXIT(1);
...
THREAD_END:
smth_destroy(...);
THREAD_FINISH(arg);
}
You may pass an context variable into thread in t_init(), like workload_t
in this example. THREAD_ENTRY macro declares it and special variable 'thread':
thread_t* thread;
workload_t* wl;
NOTES
On Solaris mutex_ and cv_ function names are reserved by libc, so threads library prefixes it's names with ts.
Constants
THREAD_KEY_INITIALIZER, THREAD_EVENT_INITIALIZER, THREAD_MUTEX_INITIALIZER
Default object initializers
#define THREAD_EVENT_INITIALIZER { SM_INIT(.te_impl, PLAT_THREAD_EVENT_INITIALIZER), SM_INIT(.te_name, "\0") }
#define THREAD_MUTEX_INITIALIZER { SM_INIT(.tm_impl, PLAT_THREAD_MUTEX_INITIALIZER), SM_INIT(.tm_name, "\0"), SM_INIT(.tm_is_recursive, B_FALSE) }
#define THREAD_KEY_INITIALIZER { SM_INIT(.tk_impl, PLAT_THREAD_KEY_INITIALIZER), SM_INIT(.tk_name, "\0") }
TSTACKSIZE
Default stack size of thread
#define TSTACKSIZE (64 * SZ_KB)
Functions
THREAD_ENTRY
THREAD_ENTRY macro should be inserted into beginning of thread function
declares thread_t* thread and argtype_t* arg_name (private argument passed to t_init)
#define THREAD_ENTRY(arg, arg_type, arg_name)
THREAD_FINISH, THREAD_END
THREAD_END and THREAD_FINISH are used as thread's epilogue:
THREAD_END:
De-initialization code goes here
THREAD_FINISH(arg);
}
#define THREAD_END _l_thread_exit #define THREAD_FINISH(arg)
THREAD_EXIT
THREAD_EXIT - prematurely exit from thread (works only in main function of thread)
#define THREAD_EXIT(code)
thread_start_func
Prototype of thread's function
typedef thread_result_t (*thread_start_func)(thread_arg_t arg);
mutex_init, mutex_unlock, mutex_lock, mutex_try_lock, rmutex_init, mutex_destroy
public
Mutexes
NOTES
rmutex_init() is deprecated
LIBEXPORT void mutex_init(thread_mutex_t* mutex, const char* namefmt, ...) LIBEXPORT void rmutex_init(thread_mutex_t* mutex, const char* namefmt, ...) LIBEXPORT boolean_t mutex_try_lock(thread_mutex_t* mutex) LIBEXPORT void mutex_lock(thread_mutex_t* mutex) LIBEXPORT void mutex_unlock(thread_mutex_t* mutex) LIBEXPORT void mutex_destroy(thread_mutex_t* mutex)
rwlock_unlock, rwlock_lock_write, rwlock_lock_read, rwlock_init, rwlock_destroy
public
Read-write locks
LIBEXPORT void rwlock_init(thread_rwlock_t* rwlock, const char* namefmt, ...) LIBEXPORT void rwlock_lock_read(thread_rwlock_t* rwlock) LIBEXPORT void rwlock_lock_write(thread_rwlock_t* rwlock) LIBEXPORT void rwlock_unlock(thread_rwlock_t* rwlock) LIBEXPORT void rwlock_destroy(thread_rwlock_t* rwlock)
cv_destroy, cv_wait_timed, cv_wait, cv_init, cv_notify_one, cv_notify_all
public
Condition variables
LIBEXPORT void cv_init(thread_cv_t* cv, const char* namefmt, ...) LIBEXPORT void cv_wait(thread_cv_t* cv, thread_mutex_t* mutex) LIBEXPORT void cv_wait_timed(thread_cv_t* cv, thread_mutex_t* mutex, ts_time_t timeout) LIBEXPORT void cv_notify_one(thread_cv_t* cv) LIBEXPORT void cv_notify_all(thread_cv_t* cv) LIBEXPORT void cv_destroy(thread_cv_t* cv)
tkey_get, tkey_init, tkey_set, tkey_destroy
public
Thread-local storage
LIBEXPORT void tkey_init(thread_key_t* key, const char* namefmt, ...) LIBEXPORT void tkey_destroy(thread_key_t* key) LIBEXPORT void tkey_set(thread_key_t* key, void* value) LIBEXPORT void* tkey_get(thread_key_t* key)
t_self
public
returns pointer to current thread
Used to monitor mutex/event deadlock and starvation (see tutil.c)
LIBEXPORT thread_t* t_self()
t_init
public
Initialize and run thread
ARGUMENTS
-
thread - pointer to thread
-
arg - argument passed to thread
-
start - thread function
-
namefmt - format string and it's arguments for thread name
LIBEXPORT void t_init(thread_t* thread, void* arg,thread_start_func start,const char* namefmt, ...)
t_post_init
public
Post-initialize thread. Called from context of thread by THREAD_ENTRY
Inserts it to hash-map and sets platform thread id if possible
ARGUMENTS
-
t - - current thread
RETURN VALUES
t (for THREAD_ENTRY)
NOTES
Do not call this function directly, use THREAD_ENTRY macro
LIBEXPORT thread_t* t_post_init(thread_t* t)
t_exit
public
Exit from thread. Called from context of thread: notifies thread which is joined to t
and remove thread from hash_map.
NOTES
Do not call this function directly, use THREAD_EXIT macro
LIBEXPORT void t_exit(thread_t* t)
t_wait_start
public
Wait until thread starts
LIBEXPORT void t_wait_start(thread_t* t)
t_join
public
Wait until thread finishes
LIBEXPORT void t_join(thread_t* thread)
t_destroy
public
Destroy thread. If thread is still alive - join to it.
NOTES
blocks until thread exits from itself!
LIBEXPORT void t_destroy(thread_t* thread)
t_notify_state
public
LIBEXPORT void t_notify_state(thread_t* t, thread_state_t state)
threads_init, threads_fini
public
LIBEXPORT int threads_init(void) LIBEXPORT void threads_fini(void)
t_eternal_wait
publicplat
LIBEXPORT PLATAPI void t_eternal_wait(void)
t_get_pid
publicplat
LIBEXPORT PLATAPI long t_get_pid(void)
t_dump_threads
Logs how many time each thread spent on event/mutex
void t_dump_threads()
Types
thread_state_t
Thread states:
|
t_init +----------------------------------------------+
| | |
TS_INITIALIZED --> TS_RUNNABLE --+--event_wait--> TS_WAITING ----------+
| \ |
t_exit \--mutex_lock--> TS_LOCKED ----------+
|
v
TS_DEAD
typedef enum {
TS_INITIALIZED,
TS_RUNNABLE,
TS_WAITING,
TS_LOCKED,
TS_DEAD
} thread_state_t;
thread_cv_t
typedef struct {
plat_thread_cv_t tcv_impl;
char tcv_name[TEVENTNAMELEN];
} thread_cv_t;
thread_mutex_t
typedef struct {
plat_thread_mutex_t tm_impl;
char tm_name[TMUTEXNAMELEN];
boolean_t tm_is_recursive;
} thread_mutex_t;
thread_rwlock_t
typedef struct {
plat_thread_rwlock_t tl_impl;
char tl_name[TRWLOCKNAMELEN];
} thread_rwlock_t;
thread_key_t
typedef struct {
plat_thread_key_t tk_impl;
char tk_name[TKEYNAMELEN];
} thread_key_t;
thread_event_t
typedef struct {
thread_mutex_t te_mutex;
thread_cv_t te_cv;
char te_name[TEVENTNAMELEN];
} thread_event_t;
typedef unsigned thread_id_t;
typedef struct thread
Thread structure
MEMBERS
-
t_state - current state of thread. May be accessed atomically
-
t_id - unique thread id assigned by implementation library (i.e. pthreads)
-
t_local_id - local thread id assigned by user code
-
t_system_id - platform-dependent thread id (optional).
-
t_name - name of thread
-
t_mutex - protects t_state and t_condvar
-
t_condvar - notifies owner that thread is started/finished
-
t_arg - argument to a thread (processed in THREAD_ENTRY)
-
t_ret_code - return code of thread
typedef struct thread {
plat_thread_t t_impl;
plat_sched_t t_sched_impl;
thread_state_t t_state;
thread_id_t t_id;
int t_local_id;
unsigned long t_system_id;
char t_name[TNAMELEN];
/* We cannot use tutil primitives directly because
it may break TS_LOCK_DEBUG and introduce a deadlock
Fallback directly to platform versions */
plat_thread_mutex_t t_mutex;
plat_thread_cv_t t_condvar;
void* t_arg;
unsigned t_ret_code;
#ifdef TS_LOCK_DEBUG
ts_time_t t_block_time;
thread_cv_t* t_block_cv;
thread_mutex_t* t_block_mutex;
thread_rwlock_t* t_block_rwlock;
#endif
struct thread* t_next; /*< Next thread in global thread list*/
struct thread* t_pool_next; /*< Next thread in pool*/
} thread_t;