diff --git a/study/patch/mutex/Makefile b/study/patch/mutex/Makefile new file mode 100644 index 0000000..60b5ac2 --- /dev/null +++ b/study/patch/mutex/Makefile @@ -0,0 +1,51 @@ +target=mutex_bug sem_bug bug \ + sem_test check_lock \ + futex_test futex_bug + + +all:$(target) + +mutex_bug:lock_bug.c + $(CC) $^ -o $@ $(LDFLAGS) -lpthread -DMUTEX + @echo "mutex lock..." + +sem_bug:lock_bug.c + $(CC) $^ -o $@ $(LDFLAGS) -lpthread -DSEM + @echo "mutex lock..." + +bug:lock_bug.c + $(CC) $^ -o $@ $(LDFLAGS) -lpthread + @echo "none lock..." + +sem_test:sem_test.c + $(CC) $^ -o $@ $(LDFLAGS) -lpthread + @echo "bug use mutex..." + + +check_lock:check_lock.c + $(CC) $^ -o $@ $(LDFLAGS) -lpthread + @echo "check lock..." + + +futex_bug:futex_bug.c + $(CC) $^ -o $@ $(LDFLAGS) -lpthread + @echo "bug use futex..." + + +futex_test:futex_test.c + $(CC) $^ -o $@ $(LDFLAGS) -lpthread + @echo "futex workthread sendthread..." + + +bind:bind.c + $(CC) $^ -o $@ $(LDFLAGS) -lpthread + @echo "set cpu affine..." +#%.o : %.c +# $(CC) -c $^ -o $@ $(CFLAGS) $(DEFINES) +# +#%.o : %.cpp +# $(CXX) -c $^ -o $@ $(CFLAGS) $(DEFINES) + +clean : + rm -rf *.o + rm -rf $(target) diff --git a/study/patch/mutex/bind.c b/study/patch/mutex/bind.c new file mode 100644 index 0000000..0b699df --- /dev/null +++ b/study/patch/mutex/bind.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include + +#define __USE_GNU +#include +#include +#include +#include +#define THREAD_MAX_NUM 100 //1个CPU内的最多进程数 + +int num=0; //cpu中核数 +void* threadFun(void* arg) //arg 传递线程标号(自己定义) +{ + cpu_set_t mask; //CPU核的集合 + cpu_set_t get; //获取在集合中的CPU + int *a = (int *)arg; + printf("the a is:%d\n",*a); //显示是第几个线程 + CPU_ZERO(&mask); //置空 + CPU_SET(*a,&mask); //设置亲和力值 + if (sched_setaffinity(0, sizeof(mask), &mask) == -1)//设置线程CPU亲和力 + { + printf("warning: could not set CPU affinity, continuing...\n"); + } + while (1) + { + CPU_ZERO(&get); + if (sched_getaffinity(0, sizeof(get), &get) == -1)//获取线程CPU亲和力 + { + printf("warning: cound not get thread affinity, continuing...\n"); + } + int i; + for (i = 0; i < num; i++) + { + if (CPU_ISSET(i, &get))//判断线程与哪个CPU有亲和力 + { + printf("this thread %d is running processor : %d\n", i,i); + } + } + } + + return NULL; +} + +int main(int argc, char* argv[]) +{ + num = sysconf(_SC_NPROCESSORS_CONF); //获取核数 + pthread_t thread[THREAD_MAX_NUM]; + printf("system has %i processor(s). \n", num); + int tid[THREAD_MAX_NUM]; + int i; + for(i=0;i +#include +#include +#include + +#define MAX_COUNT 64 + +typedef struct tagMute +{ + pthread_mutex_t mutex; + char file[128]; + int line; + int mute_status; + struct tagPLAYER * tag_player; +} T_MUTE; + +typedef struct tagPLAYER +{ + T_MUTE *player_mux; +}T_PLAYER; + +typedef struct tagLIST +{ + int list_count; + T_MUTE *list[MAX_COUNT]; +}T_LIST; + +typedef struct tagARG +{ + + int shareA, shareB; + int count; + T_PLAYER *player_A, *player_B; +}T_ARG; + +T_LIST *list; + +#define PLAYER_MUXTEX_INIT(x) do {\ +T_PLAYER *player = (T_PLAYER *)x;\ +pthread_mutex_init(&(player->player_mux->mutex), NULL);\ +memset(player->player_mux->file, 0, sizeof(player->player_mux->file));\ +player->player_mux->line = 0;\ +player->player_mux->mute_status = 0;\ +player->player_mux->tag_player = player;\ +list->list[list->list_count++] = player->player_mux;\ +}while(0) + +#define PLAYER_MUXTEX_LOCK(x) do {\ + T_PLAYER *player = (T_PLAYER *)x;\ + pthread_mutex_lock(&(player->player_mux->mutex));\ + strncpy(player->player_mux->file, __FILE__, sizeof(player->player_mux->file));\ + player->player_mux->line = __LINE__;\ + player->player_mux->mute_status = 1;\ +}while (0) + +#define PLAYER_MUXTEX_UNLOCK(x) do {\ + T_PLAYER *player = (T_PLAYER *)x;\ + player->player_mux->mute_status = 0;\ + pthread_mutex_unlock(&player->player_mux->mutex);\ +}while(0) + +#define PLAYER_MUXTEX_DESTROY do {\ + while(list->list_count){\ + pthread_mutex_destroy(&list->list[list->list_count-1]->mutex);\ + free(list->list[list->list_count-1]);\ + list->list_count--;\ + }\ +}while(0) + +void handle_dead_lock(void) +{ + int index; +flag: + printf("Please input unlock index: "); + scanf("%d", &index); + + if((index >= 0) &&(index < list->list_count)) + { + PLAYER_MUXTEX_UNLOCK(list->list[index]->tag_player); + } + else + { + printf("Input error!\n"); + goto flag; + } +} + +void *loop_detect_deadlock_thread(void *arg) +{ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); + + T_ARG *argDetect = (T_ARG *)arg; + int i = 0; + while(1) + { + T_MUTE *mutex = list->list[i]; + + pthread_mutex_lock(&mutex->mutex); + argDetect->count ++; + pthread_mutex_unlock(&mutex->mutex); + + + i = (++i) % list->list_count; + pthread_testcancel(); + sleep(1); + } +} + +void *loop_detect_count_thread(void *arg) +{ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); + + T_ARG *argCount = (T_ARG *)arg; + do + { + int temp = argCount->count; + sleep(5); + if(temp == argCount->count) + { + printf("dead lock!\n"); + int i = 0; + for(i = 0; i < list->list_count; i++) + { + if(list->list[i]->mute_status) + { + printf("%d\tlock at %s:%d\n",i, list->list[i]->file, list->list[i]->line); + } + } + handle_dead_lock(); + } + }while(1); +} + +void * thread_fun_A(void * arg) +{ + T_ARG *argA = (T_ARG *)arg; + PLAYER_MUXTEX_LOCK(argA->player_A); + printf("threadA lock playerA, shareA = %d, shareB = %d\n", argA->shareA, argA->shareB); + +// printf("shareA = shareA(%d) + 2\n", shareA); + argA->shareA += 2; + + + sleep(1); + PLAYER_MUXTEX_LOCK(argA->player_B); + printf("threadA lock playerB, shareA = %d, shareB = %d\n", argA->shareA, argA->shareB); + +// printf("shareA = shareB(%d) + 2\n", shareB); + argA->shareA = argA->shareB + 2; + + + PLAYER_MUXTEX_UNLOCK(argA->player_B); + printf("threadA unlock playerB, shareA = %d, shareB = %d\n", argA->shareA, argA->shareB); + + PLAYER_MUXTEX_UNLOCK(argA->player_A); + printf("threadA unlock playerA, shareA = %d, shareB = %d\n", argA->shareA, argA->shareB); +} + +void * thread_fun_B(void * arg) +{ + T_ARG *argB = (T_ARG *)arg; + + PLAYER_MUXTEX_LOCK(argB->player_B); + printf("threadB lock playerB, shareA = %d, shareB = %d\n", argB->shareA, argB->shareB); + +// printf("shareB = shareB(%d) + 3\n", shareB); + argB->shareB += 3; + + + sleep(1); + PLAYER_MUXTEX_LOCK(argB->player_A); + printf("threadB lock playerA, shareA = %d, shareB = %d\n", argB->shareA, argB->shareB); + +// printf("shareB = shareA(%d) + 3\n", shareA); + argB->shareB = argB->shareA + 3; + + + PLAYER_MUXTEX_UNLOCK(argB->player_A); + printf("threadB unlock playerA, shareA = %d, shareB = %d\n", argB->shareA, argB->shareB); + + PLAYER_MUXTEX_UNLOCK(argB->player_B); + printf("threadB unlock playerB, shareA = %d, shareB = %d\n", argB->shareA, argB->shareB); +} + +void init(T_ARG *arg) +{ + arg->shareA = 0; + arg->shareB = 0; + arg->count = 0; + + list = (T_LIST *)malloc(sizeof(T_LIST)); + list->list_count = 0; + + arg->player_A = (T_PLAYER *)malloc(sizeof(T_PLAYER)); + arg->player_B = (T_PLAYER *)malloc(sizeof(T_PLAYER)); + + arg->player_A->player_mux = (T_MUTE *)malloc(sizeof(T_MUTE)); + arg->player_B->player_mux = (T_MUTE *)malloc(sizeof(T_MUTE)); + + PLAYER_MUXTEX_INIT(arg->player_A); + PLAYER_MUXTEX_INIT(arg->player_B); +} + +void free_player(T_ARG *arg) +{ + free(arg->player_A); + free(arg->player_B); + + free(arg); + + free(list); +} +int main(int argc, char * argv[]) +{ + T_ARG *arg = (T_ARG *)malloc(sizeof(T_ARG)); + + init(arg); + + int ret = -1; + + pthread_t threadA, threadB, thread_detect_deadlock, thread_detect_count; + ret = pthread_create(&threadA, NULL, thread_fun_A, (void *)arg); + if(ret != 0) + { + printf("Pthread create error!\n"); + } + + ret = pthread_create(&threadB, NULL, thread_fun_B, (void *)arg); + if(ret != 0) + { + printf("Pthread create error!\n"); + } + + ret = pthread_create(&thread_detect_deadlock, NULL, loop_detect_deadlock_thread, (void *)arg); + if(ret != 0) + { + printf("Pthread create error!\n"); + } + + ret = pthread_create(&thread_detect_count, NULL, loop_detect_count_thread, (void *)arg); + if(ret != 0) + { + printf("Pthread create error!\n"); + } + + pthread_join(threadA, NULL); + pthread_join(threadB, NULL); + + pthread_cancel(thread_detect_count); + pthread_cancel(thread_detect_deadlock); + pthread_join(thread_detect_count, NULL); + pthread_join(thread_detect_deadlock, NULL); + + PLAYER_MUXTEX_DESTROY; + + printf("shareA: %d, shareB: %d\n", arg->shareA, arg->shareB); + free_player(arg); +} diff --git a/study/patch/mutex/futex_bug.c b/study/patch/mutex/futex_bug.c new file mode 100644 index 0000000..8403880 --- /dev/null +++ b/study/patch/mutex/futex_bug.c @@ -0,0 +1,110 @@ +// 2010年 07月 28日 星期三 13:01:43 CST +// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng) +// K.I.S.S +// S.P.O.T +// linux-2.6.XX/Document/ +// linux-2.6.xx/kernel/futex.c +// http://blog.csdn.net/cybertan/article/details/8096863 +#include +#include + +#include +#include +#include +#include +#include + + +#include + +#define gettid( ) syscall(SYS_gettid) + +#define futex(addr1, op, val, rel, addr2, val3) \ + syscall(SYS_futex, addr1, op, val, rel, addr2, val3) + +typedef struct futex_t { + int wake; + int lock; + int wlock; +}futex_t; + +inline static void futex_init(futex_t *); +inline static int futex_wake(futex_t *); +inline static int futex_wait(futex_t *); +inline static int futex_lock(futex_t *); +inline static int futex_unlock(futex_t *); + + +static void *work_thread(void *); +static void *work_send(void *); + +static int count = 0; + +int main() +{ + struct futex_t ftx; + pthread_t tid[2]; + + futex_init(&ftx); + + pthread_create(&tid[0], 0, work_thread, (void *)&ftx); + pthread_create(&tid[1], 0, work_thread, (void *)&ftx); + + for(int i = 0; i < 2; ++i) + pthread_join(tid[i], 0); + + return 0; +} + +void *work_thread(void *p) +{ + struct futex_t *ftx = (struct futex_t *)p; + //sleep(2); + + for(;;) { + futex_wait(ftx); + futex_lock(ftx); + + printf("tid = %d, count = %ld\n", gettid( ), count); + count++; + usleep(1000000); + + futex_unlock(ftx); + futex_wake(ftx); + } + return (void *)0; +} + + +inline static void futex_init(futex_t *ftx) +{ + ftx->lock = 0; + ftx->wake = 0; + ftx->wlock = 0; +} + +inline static int futex_wake(futex_t *ftx) +{ + __sync_fetch_and_add(&ftx->wake, 1); + //__sync_lock_test_and_set(&ftx->wake, 1); + return futex(&ftx->wake, FUTEX_WAKE, 1, 0, 0, 0); +} + +inline static int futex_wait(futex_t *ftx) +{ + futex(&ftx->wlock, FUTEX_LOCK_PI, 0, 0, 0, 0); + int ret = futex(&ftx->wake, FUTEX_WAIT, 0, 0, 0, 0); + __sync_fetch_and_sub(&ftx->wake, 1); + futex(&ftx->wlock, FUTEX_UNLOCK_PI, 0, 0, 0, 0); + return (ret && errno == EWOULDBLOCK ? 1 : ret); +} + +inline static int futex_lock(futex_t *ftx) +{ + return futex(&ftx->lock, FUTEX_LOCK_PI, 0, 0, 0, 0); +} + +inline static int futex_unlock(futex_t *ftx) +{ + return futex(&ftx->lock, FUTEX_UNLOCK_PI, 0, 0, 0, 0); +} diff --git a/study/patch/mutex/futex_test.c b/study/patch/mutex/futex_test.c new file mode 100644 index 0000000..bdf0ffe --- /dev/null +++ b/study/patch/mutex/futex_test.c @@ -0,0 +1,120 @@ +// 2010年 07月 28日 星期三 13:01:43 CST +// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng) +// K.I.S.S +// S.P.O.T +// linux-2.6.XX/Document/ +// linux-2.6.xx/kernel/futex.c +// http://blog.csdn.net/cybertan/article/details/8096863 +#include + +#include +#include +#include +#include +#include + + +#include + +#define gettid( ) syscall(SYS_gettid) + +#define futex(addr1, op, val, rel, addr2, val3) \ + syscall(SYS_futex, addr1, op, val, rel, addr2, val3) + +typedef struct futex_t { + int wake; + int lock; + int wlock; +}futex_t; + +inline static void futex_init(futex_t *); +inline static int futex_wake(futex_t *); +inline static int futex_wait(futex_t *); +inline static int futex_lock(futex_t *); +inline static int futex_unlock(futex_t *); + + +static void *work_thread(void *); +static void *work_send(void *); + +static int count = 0; + +int main() +{ + struct futex_t ftx; + pthread_t tid[6]; + + futex_init(&ftx); + + pthread_create(&tid[3], 0, work_send, (void *)&ftx); + pthread_create(&tid[1], 0, work_thread, (void *)&ftx); + pthread_create(&tid[2], 0, work_thread, (void *)&ftx); + pthread_create(&tid[5], 0, work_send, (void *)&ftx); + pthread_create(&tid[0], 0, work_thread, (void *)&ftx); + pthread_create(&tid[4], 0, work_send, (void *)&ftx); + + for(int i = 0; i < 6; ++i) + pthread_join(tid[i], 0); + + return 0; +} + +void *work_thread(void *p) +{ + struct futex_t *ftx = (struct futex_t *)p; + //sleep(2); + + for(;;) { + futex_wait(ftx); + + futex_lock(ftx); + + printf("tid = %d, count = %ld\n", gettid( ), count); + count++; + usleep(1000000); + + futex_unlock(ftx); + } + return (void *)0; +} + +void *work_send(void *p) +{ + futex_t *ftx = (struct futex_t *)p; + for(int i = 0; i < 3000; ++i) + futex_wake(ftx); + return (void *)0; +} + +inline static void futex_init(futex_t *ftx) +{ + ftx->lock = 0; + ftx->wake = 0; + ftx->wlock = 0; +} + +inline static int futex_wake(futex_t *ftx) +{ + __sync_fetch_and_add(&ftx->wake, 1); + //__sync_lock_test_and_set(&ftx->wake, 1); + return futex(&ftx->wake, FUTEX_WAKE, 1, 0, 0, 0); +} + +inline static int futex_wait(futex_t *ftx) +{ + futex(&ftx->wlock, FUTEX_LOCK_PI, 0, 0, 0, 0); + int ret = futex(&ftx->wake, FUTEX_WAIT, 0, 0, 0, 0); + __sync_fetch_and_sub(&ftx->wake, 1); + futex(&ftx->wlock, FUTEX_UNLOCK_PI, 0, 0, 0, 0); + return (ret && errno == EWOULDBLOCK ? 1 : ret); +} + +inline static int futex_lock(futex_t *ftx) +{ + return futex(&ftx->lock, FUTEX_LOCK_PI, 0, 0, 0, 0); +} + +inline static int futex_unlock(futex_t *ftx) +{ + return futex(&ftx->lock, FUTEX_UNLOCK_PI, 0, 0, 0, 0); +} diff --git a/study/patch/mutex/lock_bug.c b/study/patch/mutex/lock_bug.c new file mode 100644 index 0000000..fbf8d9e --- /dev/null +++ b/study/patch/mutex/lock_bug.c @@ -0,0 +1,116 @@ +/************************************************************************* + > File Name: mutex_bug.c + > Author: GatieMe + > Mail: gatieme@163.com + > Created Time: Sat 09 Sep 2017 11:39:26 AM CST + ************************************************************************/ + +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include + +#include /* For pthread */ + +#include /* */ + +#include +#include + +#if defined(MUTEX) + pthread_mutex_t lock; + #define LOCK_INIT( ) pthread_mutex_init(&lock, NULL) + #define LOCK( ) pthread_mutex_lock(&lock) + #define UNLOCK( ) pthread_mutex_unlock(&lock) + #define LOCK_DESTROY( ) pthread_mutex_destroy(&lock) +#elif defined(SEM) + #include + sem_t lock; + #define LOCK_INIT( ) sem_init(&lock, 0, 1) + #define LOCK( ) sem_wait(&lock) + #define UNLOCK( ) sem_post(&lock) + #define LOCK_DESTROY( ) sem_destroy(&lock) +#else + #define LOCK_INIT( ) + #define LOCK( ) + #define UNLOCK( ) + #define LOCK_DESTROY( ) +#endif + + +#if 0 +#include +pid_t gettid(void) +{ + return syscall(__NR_gettid); +} +#endif +#include + +pid_t gettid(void) +{ + return syscall(SYS_gettid); +} +struct args +{ + unsigned long sleeptime; + int cpu; +}; + +void *print_msg(void *arg){ + + unsigned long count = 0; + struct args *curr_arg = (struct args*)arg; + cpu_set_t mask; + + printf("tid = %d(%ld) START\n", gettid( ), pthread_self( )); + + + CPU_ZERO(&mask); + //CPU_SET(curr_arg->cpu, &mask); + CPU_SET(0, &mask); + + if (pthread_setaffinity_np(pthread_self( ), sizeof(mask), &mask) < 0) { + perror("sched_setaffinity"); + } + else + { + printf("tid = %d affine to CPU %d\n", gettid( ), curr_arg->cpu); + } + + while( 1 ) + { + LOCK( ); + + printf("tid = %d, count = %ld\n", gettid( ), count); + count++; + usleep(curr_arg->sleeptime); + + UNLOCK( ); + } +} + +int main(int argc,char** argv){ + pthread_t id1; + pthread_t id2; + + struct args arg1 = { .sleeptime = 1000000, .cpu = 0 }; + struct args arg2 = { .sleeptime = 1000000, .cpu = 0 }; + + LOCK_INIT( ); + + + printf("MAIN pid = %d\n", getpid( )); + + + pthread_create(&id1, NULL, print_msg, &arg1); + pthread_create(&id2, NULL, print_msg, &arg2); + + pthread_join(id1, NULL); + pthread_join(id2, NULL); + + LOCK_DESTROY( ); + + return EXIT_SUCCESS; +} + + + diff --git a/study/patch/mutex/mutex.stp b/study/patch/mutex/mutex.stp new file mode 100644 index 0000000..f0245ee --- /dev/null +++ b/study/patch/mutex/mutex.stp @@ -0,0 +1,44 @@ + +probe begin +{ + printf("futex begin\n"); +} + +probe kernel.function("do_futex") +{ + if(pid( ) == target( )) + { + printf("[do_futex] : tid = %d\n", tid( )); + } +} + +probe kernel.function("futex_wait") +{ + if(pid( ) == target( )) + { + printf("[futex_wait] : tid = %d\n", tid( )); + } +} + +probe kernel.function("futex_wake") +{ + if(pid( ) == target( )) + { + printf("[futex_wake] : tid = %d\n", tid( )); + } +} + +probe kernel.function("__schedule") +{ + if(pid( ) == target( )) + { + printf("[__schedule] : tid = %d\n", tid( )); + + } +} +probe end +{ + printf("futex end\n"); +} + + diff --git a/study/patch/mutex/mutex_bug.c b/study/patch/mutex/mutex_bug.c new file mode 100644 index 0000000..97b3ad2 --- /dev/null +++ b/study/patch/mutex/mutex_bug.c @@ -0,0 +1,97 @@ +/************************************************************************* + > File Name: mutex_bug.c + > Author: GatieMe + > Mail: gatieme@163.com + > Created Time: Sat 09 Sep 2017 11:39:26 AM CST + ************************************************************************/ + +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include + +#include /* For pthread */ + +#include /* */ + +#include +#include + +#include + +pid_t gettid(void) +{ + return syscall(SYS_gettid); +} +struct args +{ + unsigned long sleeptime; + int cpu; +}; + + + #include + #include + +#define futex(addr1, op, val, rel, addr2, val3) \ + syscall(SYS_futex, addr1, op, val, rel, addr2, val3) + +long lock; +void *print_msg(void *arg){ + + unsigned long count = 0; + struct args *curr_arg = (struct args*)arg; + cpu_set_t mask; + + printf("tid = %d(%ld) START\n", gettid( ), pthread_self( )); + + + CPU_ZERO(&mask); + //CPU_SET(curr_arg->cpu, &mask); + CPU_SET(0, &mask); + + if (pthread_setaffinity_np(pthread_self( ), sizeof(mask), &mask) < 0) { + perror("sched_setaffinity"); + } + else + { + printf("tid = %d affine to CPU %d\n", gettid( ), curr_arg->cpu); + } + + while( 1 ) + { + futex(&lock, FUTEX_WAIT, 1, NULL, NULL, 0); + + printf("tid = %d, count = %ld\n", gettid( ), count); + count++; + usleep(curr_arg->sleeptime); + + futex(&lock, FUTEX_WAKE, 0, NULL, NULL, 0); + + } +} + +int main(int argc,char** argv){ + pthread_t id1; + pthread_t id2; + + struct args arg1 = { .sleeptime = 1000000, .cpu = 0 }; + struct args arg2 = { .sleeptime = 1000000, .cpu = 0 }; + + + lock = 1; + + printf("MAIN pid = %d\n", getpid( )); + + + pthread_create(&id1, NULL, print_msg, &arg1); + pthread_create(&id2, NULL, print_msg, &arg2); + + pthread_join(id1, NULL); + pthread_join(id2, NULL); + + + + return EXIT_SUCCESS; +} + + + diff --git a/study/patch/mutex/sem_test.c b/study/patch/mutex/sem_test.c new file mode 100644 index 0000000..78a5535 --- /dev/null +++ b/study/patch/mutex/sem_test.c @@ -0,0 +1,37 @@ +// http://blog.csdn.net/jianchaolv/article/details/7544316 +#include +#include +#include +#include + + +sem_t sem_a; +void *task1(); + +int main(void){ + int ret = 0; + pthread_t thrd1; + pthread_t thrd2; + + printf("pid = %d\n", getpid( )); + sem_init(&sem_a,0,1); + ret=pthread_create(&thrd1,NULL,task1,NULL); //创建子线程 + ret=pthread_create(&thrd2,NULL,task1,NULL); //创建子线程 + + pthread_join(thrd1,NULL); //等待子线程结束 + pthread_join(thrd2,NULL); //等待子线程结束 + +} + +void *task1() +{ + int sval = 0; + while(1) + { + sem_wait(&sem_a); //持有信号量 + sleep(1); //do_nothing + sem_getvalue(&sem_a,&sval); + printf("tid = %ld, sem value = %d\n", pthread_self( ), sval); + sem_post(&sem_a); //释放信号量 + } +}