#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
#include <unistd.h> long sysconf(int name);
#include <pthread.h> int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *attr);
常見的 thread attributes
detachstate
#include <pthread.h> int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); /* Returns zero on success, or non-zero error codes */
int makethread(void *(*fn)(void *), void *arg) { int err; pthread_t tid; pthread_attr_t attr; err = pthread_attr_init(&attr); if (err != 0) { return(err); } err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (err == 0) { err = pthread_create(&tid, &attr, fn, arg); } pthread_attr_destroy(&attr); return(err);
Thread stack address and size
#include <pthread.h> int pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr, size_t stacksize); int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize); /* Returns zero on success, or non-zero error codes */
#include <pthread.h> int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize); int pthread_attr_setstacksize(pthread_attr_t *attr , size_t stacksize); /* Return zero on success, or non-zero error codes */
guardsize
#include <pthread.h> int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize); int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); /* Return zero on success, or non-zero error codes */
#include <pthread.h> int pthread_mutexattr_init(pthread_mutexattr_t *attr); int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); int pthread_rwlockattr_init(pthread_rwlockattr_t *attr); int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr); int pthread_condattr_init(pthread_condattr_t *attr); int pthread_condattr_destroy(pthread_condattr_t *attr); /* Returns zero on success, or non-zero error codes */
Mutex 互斥鎖
#include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex); // 請求鎖,如果當前 mutex 已經被鎖,那這個執行緒就會卡在這,直到mutex被釋放 int pthread_mutex_unlock(pthread_mutex_t *mutex); // 解鎖 int pthread_mutex_trylock(pthread_mutex_t *mutex); // 嘗試請求鎖,如果當前 mutex 已經被鎖或者不可用,這個函數就直接 return error,不會把執行緒卡住
常見的 Mutex Attributes
Mutex Attribute: Process-Shared
#include <pthread.h> int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict attr, int *restrict pshared); /* Returns zero on success and store pshared in pshared parameter, or non-zero error codes */ int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type); int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared); /* Returns zero on success, or non-zero error codes */
Mutex Attribute: Type
Mutex type | Reloack without unlock? | Unlock when not owned? | Unlock when unlocked? |
---|---|---|---|
PTHREAD_MUTEX_NORMAL | deadlock | undefined | undefined |
PTHREAD_MUTEX_ERRORCHECK | returns error | returns error | returns error |
PTHREAD_MUTEX_RECURSIVE | allowed | returns error | returns error |
PTHREAD_MUTEX_DEFAULT | system dependent | system dependent | system dependent |
#include <pthread.h> int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict attr, int *restrict type); /* Returns zero on success and store type in type parameter, or non-zero error codes */ int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type); /* Returns zero on success, or non-zero error codes */
Reader-Writter Lock 讀寫鎖
#include <pthread.h> int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
How To
pthread key
#include <pthread.h> int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *)); int pthread_key_delete(pthread_key_t *key);
/* 若這樣寫,在 if 那邊可能會產生 race conditions */ void destructor(void *); pthread_key_t key; int init_done = 0; int threadfunc(void *arg) { if(!init_done) { init_done = 1; err = pthread_key_create(&key, destructor); } ... }
pthread_once_t initflag = PTHREAD_ONCE_INIT; int pthread_once(pthread_once_t *initflag, void (*initfn)(void)); void destructor(void *); pthread_key_t key; pthread_once_t init_done = PTHREAD_ONCE_INIT; void thread_init(void) { err = pthread_key_create(&key, destructor); } int threadfunc(void *arg) { pthread_once(&init_done, thread_init); ... }
get, associate and de-associate data
#include <pthread.h> void *pthread_getspecific(pthread_key_t key); /* Return non-NULL for the associated value, or NULL if no value has been associated with the key */
#include <pthread.h> int pthread_setspecific(pthread_key_t key, const void *value); /* Return zero on success, or non-error error codes */
static pthread_key_t key; static pthread_once_t init_done = PTHREAD_ONCE_INIT; pthread_mutex_t env_mutex = PTHREAD_MUTEX_INITIALIZER; extern char **environ; static void thread_init(void) { pthread_key_create(&key, free); } char * getenv(const char *name) { int i, len; char *envbuf; pthread_once(&init_done, thread_init); pthread_mutex_lock(&env_mutex); envbuf = (char *) pthread_getspecific(key); if (envbuf == NULL) { if((envbuf = malloc(ARG_MAX)) == NULL) { pthread_mutex_unlock(&env_mutex); return(NULL); } pthread_setspecific(key, envbuf); } len = strlen(name); for (i = 0; environ[i] != NULL; i++) { if ((strncmp(name, environ[i], len) == 0) && (environ[i][len] == '=')) { strcpy(envbuf, &environ[i][len+1]); pthread_mutex_unlock(&env_mutex); return(envbuf); } } pthread_mutex_unlock(&env_mutex); return(NULL); }