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;