#include <pthread.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <assert.h>static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t waite_recv = PTHREAD_COND_INITIALIZER;static pthread_cond_t waite_send = PTHREAD_COND_INITIALIZER;static volatile int message = 0;static volatile int sem_counts = 0;static volatile int mut_counts = 0;#define DO_COUNTS 90000000int get_sem_counts(){ return sem_counts;}int get_mut_counts(){ return mut_counts;}void reset_mut_counts(){ mut_counts = 0;}#define CHECK_ROUTE( x ) do{\ int __ret__ = x;\ if( 0 != __ret__ ){\ printf("[%s:%d]:%d-%d(%s)\n",__FUNCTION__,__LINE__,__ret__,errno,strerror(errno));\ return NULL;\ }\}while(0)static void* recv_thread(void* arg) { int i = 0; for (;i < DO_COUNTS/100; ++i) { CHECK_ROUTE(pthread_mutex_lock(&mutex)); /* * be care this wait may be excute after * broadcast or signal * in that way U may be lost one condtion * at least even may be dead lock here * so we must introduce a var to test * whether ok. */ for(; 0 == message;) { CHECK_ROUTE(pthread_cond_wait(&waite_send, &mutex)); } --message; CHECK_ROUTE(pthread_cond_signal(&waite_recv)); CHECK_ROUTE(pthread_mutex_unlock(&mutex)); ++mut_counts; } return NULL;}static void* send_thread(void* arg) { int i = 0; for (;i < DO_COUNTS/100; ++i) { CHECK_ROUTE(pthread_mutex_lock(&mutex)); ++message; /** * be care this route may be no using when * there're no any thread waite this conition * so must changed this usage */ CHECK_ROUTE(pthread_cond_signal(&waite_send)); CHECK_ROUTE(pthread_cond_wait(&waite_recv, &mutex)); CHECK_ROUTE(pthread_mutex_unlock(&mutex)); } return NULL;}/* * this test could work but .... */void* test_mutex_for_semphone(){ pthread_t recver,sender; int i,k; void *r = &i,*s = &k; message = 0; CHECK_ROUTE(pthread_mutex_init(&mutex,NULL)); CHECK_ROUTE(pthread_cond_init(&waite_recv,NULL)); CHECK_ROUTE(pthread_cond_init(&waite_send,NULL)); CHECK_ROUTE(pthread_create(&recver,NULL,recv_thread,NULL)); CHECK_ROUTE(pthread_create(&sender,NULL,send_thread,NULL)); CHECK_ROUTE(pthread_join(recver,&r)); CHECK_ROUTE(pthread_join(sender,&s)); CHECK_ROUTE(pthread_cond_destroy(&waite_recv)); CHECK_ROUTE(pthread_cond_destroy(&waite_send)); CHECK_ROUTE(pthread_mutex_destroy(&mutex)); assert(message == 0);}#include <semaphore.h>static sem_t send_sem;static sem_t recv_sem;void* sem_send_thread(void* arg){ int i = 0; for(; i < DO_COUNTS/100; ++i){ ++message; CHECK_ROUTE(sem_post(&send_sem)); CHECK_ROUTE(sem_wait(&recv_sem)); } return NULL;}void* sem_recv_thread(){ int i = 0; for(; i < DO_COUNTS/100; ++i){ CHECK_ROUTE(sem_wait(&send_sem)); --message; ++mut_counts; CHECK_ROUTE(sem_post(&recv_sem)); ++sem_counts; } return NULL; }void* test_emphone(){ pthread_t recver,sender; int i,k; void *r = &i,*s = &k; message = 0; CHECK_ROUTE(sem_init(&send_sem,0,0)); CHECK_ROUTE(sem_init(&recv_sem,0,0)); CHECK_ROUTE(pthread_create(&recver,NULL,sem_recv_thread,NULL)); CHECK_ROUTE(pthread_create(&sender,NULL,sem_send_thread,NULL)); CHECK_ROUTE(pthread_join(recver,&r)); CHECK_ROUTE(pthread_join(sender,&s)); CHECK_ROUTE(sem_destroy(&send_sem)); CHECK_ROUTE(sem_destroy(&recv_sem)); assert(message == 0);}/* * * using sem as a mutex to metex var operation * no any other process * */static sem_t sem_mutex;static void* sem_mutex_recv_thread(void* arg){ int i = 0; for(; i < DO_COUNTS ; ++i){ CHECK_ROUTE(sem_wait(&sem_mutex)); --message; ++mut_counts; CHECK_ROUTE(sem_post(&sem_mutex)); }}static void* sem_mutex_send_thread(void* arg){ int i = 0; for(; i < DO_COUNTS ; ++i){ CHECK_ROUTE(sem_wait(&sem_mutex)); ++message; CHECK_ROUTE(sem_post(&sem_mutex)); }}void* test_sem_for_mutex(){ pthread_t recver,sender; int i,k; void *r = &i,*s = &k; message = 0; CHECK_ROUTE(sem_init(&sem_mutex,0,1)); CHECK_ROUTE(pthread_create(&recver,NULL,sem_mutex_recv_thread,NULL)); CHECK_ROUTE(pthread_create(&sender,NULL,sem_mutex_send_thread,NULL)); CHECK_ROUTE(pthread_join(recver,&r)); CHECK_ROUTE(pthread_join(sender,&s)); CHECK_ROUTE(sem_destroy(&sem_mutex)); assert(message == 0);}/* * * only test for mutex var operation * no any other process * */static void* mutex_recv_thread(void* arg){ int i = 0; for(; i < DO_COUNTS ; ++i){ CHECK_ROUTE(pthread_mutex_lock(&mutex)); --message; ++mut_counts; CHECK_ROUTE(pthread_mutex_unlock(&mutex)); } }static void* mutex_send_thread(void* arg){ int i = 0; for(; i < DO_COUNTS ; ++i){ CHECK_ROUTE(pthread_mutex_lock(&mutex)); ++message; CHECK_ROUTE(pthread_mutex_unlock(&mutex)); }}void* test_mutex(){ pthread_t recver,sender; int i,k; void *r = &i,*s = &k; message = 0; CHECK_ROUTE(pthread_mutex_init(&mutex,NULL)); CHECK_ROUTE(pthread_create(&recver,NULL,mutex_recv_thread,NULL)); CHECK_ROUTE(pthread_create(&sender,NULL,mutex_send_thread,NULL)); CHECK_ROUTE(pthread_join(recver,&r)); CHECK_ROUTE(pthread_join(sender,&s)); CHECK_ROUTE(pthread_mutex_destroy(&mutex)); assert(message == 0);}static sem_t sem_sig;static void* sem_sig_send(void* arg) { int i = 0; for (; i < DO_COUNTS; ++i) { /* * ++ operation is not automic operation * so after following opeation the message * value not make sure * in this case */ ++message;++mut_counts; CHECK_ROUTE(sem_post(&sem_sig)); } return NULL;}static void* sem_sig_recv(void* arg){ int i = 0,k = 0; for (; i < DO_COUNTS; ++i) { CHECK_ROUTE(sem_wait(&sem_sig)); /* * this operation not safe maybe dirty read and wirte */ --message; }}void* test_sem_for_sig(){ pthread_t recver,sender; int i,k; void *r = &i,*s = &k; CHECK_ROUTE(sem_init(&sem_sig,0,0)); message = 0; CHECK_ROUTE(pthread_create(&recver,NULL,sem_sig_send,NULL)); CHECK_ROUTE(pthread_create(&sender,NULL,sem_sig_recv,NULL)); CHECK_ROUTE(pthread_join(recver,&r)); CHECK_ROUTE(pthread_join(sender,&s)); CHECK_ROUTE(sem_destroy(&sem_sig));}static pthread_mutex_t guard;static sem_t wait_object;static void* mix_send(void* arg) { int i = 0; for (; i < DO_COUNTS; ++i) { pthread_mutex_lock(&guard); ++message;++mut_counts; pthread_mutex_unlock(&guard); CHECK_ROUTE(sem_post(&wait_object)); } return NULL;}static void* mix_recv(void* arg){ int i = 0,k = 0; for (; i < DO_COUNTS; ++i) { CHECK_ROUTE(sem_wait(&wait_object)); pthread_mutex_lock(&guard); --message; pthread_mutex_unlock(&guard); } return NULL;}#include <assert.h>void* test_mix(){ pthread_t recver,sender; int i,k; void *r = &i,*s = &k; CHECK_ROUTE(sem_init(&wait_object,0,0)); CHECK_ROUTE(pthread_mutex_init(&guard,NULL)); message = 0; CHECK_ROUTE(pthread_create(&recver,NULL,mix_send,NULL)); CHECK_ROUTE(pthread_create(&sender,NULL,mix_recv,NULL)); CHECK_ROUTE(pthread_join(recver,&r)); CHECK_ROUTE(pthread_join(sender,&s)); CHECK_ROUTE(sem_destroy(&wait_object)); CHECK_ROUTE(pthread_mutex_unlock(&guard)); assert(message == 0);}
#include <time.h>/* * */void find_id_number(const char* tail_xx);void* test_mutex_for_semphone();void* test_emphone();void* test_mutex();void* test_sem_for_mutex();void* test_sem_for_sig();void* test_sem_mix();int get_sem_counts();int get_mut_counts();void reset_mut_counts();static void test_time(){ time_t now = time(NULL); int i = 0,interval = time(NULL) - now; for (; interval < 10; ++i) { test_emphone(); interval = time(NULL) - now; } printf("10 sec sem done %d:%d:%d\n", i,interval,get_sem_counts()); reset_mut_counts(); now = time(NULL); interval = time(NULL) - now; for (i = 0; interval < 10; ++i) { test_mutex_for_semphone(); interval = time(NULL) - now; } printf("10 sec mutex done %d:%d:%d\n", i,interval,get_mut_counts()); reset_mut_counts(); now = time(NULL); interval = time(NULL) - now; for (i = 0; interval < 10; ++i) { test_sem_for_mutex(); interval = time(NULL) - now; } printf("10 sec sem_for_mutex done %d:%d:%d\n", i,interval,get_mut_counts()); reset_mut_counts(); now = time(NULL); interval = time(NULL) - now; for (i = 0; interval < 10; ++i) { test_mutex(); interval = time(NULL) - now; } printf("10 sec only mutex done %d:%d:%d\n", i,interval,get_mut_counts()); reset_mut_counts(); now = time(NULL); interval = time(NULL) - now; for (i = 0; interval < 10; ++i) { test_sem_for_sig(); interval = time(NULL) - now; } printf("10 sec only sem done %d:%d:%d\n", i,interval,get_mut_counts()); reset_mut_counts(); now = time(NULL); interval = time(NULL) - now; for (i = 0; interval < 10; ++i) { test_mix(); interval = time(NULL) - now; } printf("10 sec mix done %d:%d:%d\n", i,interval,get_mut_counts()); }int main(int argc, char** argv) { test_time(); return (EXIT_SUCCESS);}
10 sec sem done 1:25:90000010 sec mutex done 1:37:90000010 sec sem_for_mutex done 1:25:9000000010 sec only mutex done 1:14:9000000010 sec only sem done 1:50:9000000010 sec mix done 1:25:90000000