acl/samples/thread/thread1/main.c

301 lines
7.6 KiB
C

#include "stdlib/acl_define_unix.h"
#ifdef ACL_UNIX
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
# include <pthread.h>
#endif
#include "lib_acl.h"
#include <time.h>
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);
}