#include "stdlib/acl_define_unix.h" #ifdef ACL_UNIX # ifndef _GNU_SOURCE # define _GNU_SOURCE # endif # include #endif #include "lib_acl.h" #include typedef struct THREAD_CTX { int i; } THREAD_CTX; #if 0 typedef volatile int pthread_spinlock_t; extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared); extern int pthread_spin_lock (pthread_spinlock_t *__lock); extern int pthread_spin_unlock (pthread_spinlock_t *__lock); #endif static void *test_thread_fn(void *arg) { THREAD_CTX *ctx = (THREAD_CTX*) arg; ctx->i++; printf("current tid is: %lu\r\n", (unsigned long int) acl_pthread_self()); return (ctx); } #ifdef ACL_UNIX static pthread_spinlock_t __spin_lock; #endif static void *thread_nested_mutex(void *arg) { acl_pthread_mutex_t *mutex = (acl_pthread_mutex_t*) arg; int m = 2; int i, n = 100000000; time_t begin, end; #ifdef ACL_UNIX if (0) { printf("tid: %lu, begin spin lock\n", (unsigned long int) acl_pthread_self()); time(&begin); for (i = 0; i < n; i++) { pthread_spin_lock(&__spin_lock); pthread_spin_unlock(&__spin_lock); } time(&end); printf("tid: %lu, lock over, spin, time: %ld\n", (unsigned long int) acl_pthread_self(), (long) end - begin); } #endif if (1) { printf("tid: %lu, begin lock mutex\n", (unsigned long int) acl_pthread_self()); time(&begin); for (i = 0; i < n; i++) { acl_thread_mutex_lock(mutex); acl_thread_mutex_unlock(mutex); } time(&end); printf("tid: %lu, lock mutex ok, nested: %d, sleep %d seconds, time: %ld\n", (unsigned long int) acl_pthread_self(), acl_thread_mutex_nested(mutex), m, (long) end - begin); } if (0) { sleep(m); printf("tid: %lu, wakeup, begin unlock\n", (unsigned long int) acl_pthread_self()); for (i = 0; i < n; i++) acl_thread_mutex_unlock(mutex); time(&end); printf("tid: %lu, time: %ld, exit now\n", (unsigned long int) acl_pthread_self(), (long) end - begin); } return (NULL); } static void test_nested_mutex(void) { acl_pthread_t tid; acl_pthread_attr_t attr; static acl_pthread_mutex_t mutex; #ifdef ACL_UNIX pthread_spin_init(&__spin_lock, 0); #endif acl_pthread_mutex_init(&mutex, NULL); acl_pthread_attr_init(&attr); acl_pthread_attr_setdetachstate(&attr, ACL_PTHREAD_CREATE_DETACHED); acl_pthread_create(&tid, &attr, thread_nested_mutex, &mutex); acl_pthread_create(&tid, &attr, thread_nested_mutex, &mutex); } #ifdef ACL_UNIX static pthread_mutex_t mutex_init1 = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t mutex_init2 = PTHREAD_MUTEX_INITIALIZER; static void test_thread(void) { acl_pthread_t tid; acl_pthread_attr_t attr; THREAD_CTX ctx, *pctx; void *return_arg; unsigned int id; acl_pthread_mutex_lock(&mutex_init1); printf("lock mutex_init1 ok\n"); acl_pthread_mutex_lock(&mutex_init2); printf("lock mutex_init2 ok\n"); ctx.i = 0; acl_pthread_attr_init(&attr); acl_pthread_create(&tid, &attr, test_thread_fn, &ctx); acl_pthread_join(tid, (void**) &return_arg); pctx = (THREAD_CTX*) return_arg; memcpy(&id, &tid, sizeof(id)); printf("ctx.i=%d, pctx->i=%d, the thread id is: %u\r\n", ctx.i, pctx->i, id); } #endif static void free_vstring(void *arg) { const char *myname = "free_vstring"; ACL_VSTRING *buf = (ACL_VSTRING*) arg; acl_vstring_free(buf); printf("%s: tid=%d, free vstring ok\n", myname, (int) acl_pthread_self()); } static void *test_tls_thread(void *arg acl_unused) { const char *myname = "test_tls_thread"; static acl_pthread_key_t key = -1; ACL_VSTRING *buf; time_t begin; int i; unsigned long tid; const char *p = acl_last_serror(); printf("%s(%d): last serror: %s, %p\n", myname, __LINE__, p, p); printf(">>>%s(%d)(tid=%d): key = %d\n", myname, __LINE__, (int) acl_pthread_self(), key); sleep(1); printf(">>>%s(%d)(tid=%d): key = %d\n", myname, __LINE__, (int) acl_pthread_self(), key); if (1) { time(&begin); for (i = 0; i < 10000000; i++) { buf = acl_pthread_tls_get(&key); if (buf == NULL) { printf(">>>%s(tid=%d): buf null, key = %d\n", myname, (int) acl_pthread_self(), key); buf = acl_vstring_alloc(256); acl_pthread_tls_set(key, buf, free_vstring); } tid = acl_pthread_self(); } printf(">>>%s(%d)(tid=%d): time cose %d seconds, tid: %ld\n", myname, __LINE__, (int) acl_pthread_self(), (int) (time(NULL) - begin), tid); acl_vstring_sprintf(buf, "%s, tid=%lu", myname, (unsigned long) acl_pthread_self()); printf(">>>%s: buf=%s\n", myname, acl_vstring_str(buf)); } else { time(&begin); for (i = 0; i < 1000000; i++) { buf = acl_vstring_alloc(256); acl_vstring_free(buf); } printf(">>>%s(%d)(tid=%d): time cose %d seconds\n", myname, __LINE__, (int) acl_pthread_self(), (int) (time(NULL) - begin)); } sleep(1); return (NULL); } static void test_tls(void) { acl_pthread_attr_t attr; acl_pthread_t t1, t2; acl_pthread_attr_init(&attr); acl_pthread_create(&t1, &attr, test_tls_thread, NULL); acl_pthread_create(&t2, &attr, test_tls_thread, NULL); acl_pthread_join(t1, NULL); acl_pthread_join(t2, NULL); printf(">>> test_tls: over now\n"); } static int __init_once_key = 0; static void init_once(void) { const char *myname = "init_once"; __init_once_key++; printf("%s(%d, tid=%d): __init_once_key=%d\n", myname, __LINE__, (int) acl_pthread_self(), __init_once_key); } static void free_buf(void *ctx) { ACL_VSTRING *buf = (ACL_VSTRING*) ctx; acl_vstring_free(buf); printf(">>>>%s(tid=%d): free vstring ok\n", __FUNCTION__, (int) acl_pthread_self()); } static void free_vbuf(void *ctx) { ACL_VSTRING *buf = (ACL_VSTRING*) ctx; acl_vstring_free(buf); printf(">>>>%s(tid=%d): free vstring ok\n", __FUNCTION__, (int) acl_pthread_self()); } static acl_pthread_once_t once_control = ACL_PTHREAD_ONCE_INIT; static void *test_once_thread(void *arg acl_unused) { ACL_VSTRING *buf; static acl_pthread_key_t buf_key = -1; static __thread ACL_VSTRING *__vbuf = NULL; acl_pthread_once(&once_control, init_once); if (__vbuf == NULL) { __vbuf = acl_vstring_alloc(256); acl_pthread_atexit_add(__vbuf, free_vbuf); } buf = (ACL_VSTRING*) acl_pthread_tls_get(&buf_key); if (buf == NULL) { buf = acl_vstring_alloc(256); acl_pthread_tls_set(buf_key, buf, free_buf); } buf = (ACL_VSTRING*) acl_pthread_tls_get(&buf_key); if (buf == NULL) printf(">>>%s(tid=%d) buf null\n", __FUNCTION__, (int) acl_pthread_self()); else printf(">>>%s(tid=%d) buf not null\n", __FUNCTION__, (int) acl_pthread_self()); printf(">>>%s: in thread %d, last error: %s\n", __FUNCTION__, (int) acl_pthread_self(), acl_last_serror()); return (NULL); } static void test_pthread_once(void) { acl_pthread_attr_t attr; acl_pthread_t t1, t2; acl_pthread_attr_init(&attr); acl_pthread_attr_setstacksize(&attr, 10240000); acl_pthread_create(&t1, &attr, test_once_thread, NULL); acl_pthread_create(&t2, &attr, test_once_thread, NULL); acl_pthread_join(t1, NULL); acl_pthread_join(t2, NULL); printf(">>> test_pthread_once: over now, enter any key to exit...\n"); getchar(); } int main(int argc acl_unused, char *argv[] acl_unused) { if (0) { test_pthread_once(); return (0); } printf("%s(%d): last serror: %s, %p\n", __FUNCTION__, __LINE__, acl_last_serror(), acl_last_serror()); if (0) { test_tls(); return (0); } #ifdef ACL_UNIX test_thread(); #endif printf(">>>>main tid: %u\n", (unsigned) acl_pthread_self()); if (0) test_nested_mutex(); while (1) sleep(10); return (0); }