目錄表

*Thread Control

0x00 Outline

0x01 Introduction

#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);

0x02 Thread limitations

#include <unistd.h>
 
long sysconf(int name);

0x03 Thread attributes

#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 */

0x04 Synchronization Attributes

#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);

0x05 Thread-Specific Data

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);
}

0x06 Cancel Options

0x 參考資料