/* Restart all threads that are waiting on the condition variable */ int acl_pthread_cond_broadcast(acl_pthread_cond_t *cond) { const char *myname = "acl_pthread_cond_broadcast"; if (cond == NULL) { acl_msg_error("%s, %s(%d): input invalid", __FILE__, myname, __LINE__); return -1; } /* If there are waiting threads not already signalled, then * signal the condition and wait for the thread to respond. */ acl_pthread_mutex_lock(cond->lock); if (cond->waiting > cond->signals) { int i, num_waiting; num_waiting = (cond->waiting - cond->signals); cond->signals = cond->waiting; for (i = 0; i < num_waiting; ++i) acl_sem_post(cond->wait_sem); /* Now all released threads are blocked here, waiting for us. * Collect them all (and win fabulous prizes!) :-) */ acl_pthread_mutex_unlock(cond->lock); for (i = 0; i < num_waiting; ++i) acl_sem_wait(cond->wait_done); } else acl_pthread_mutex_unlock(cond->lock); return 0; }
bool rpc_request::cond_signal() { int status; status = acl_pthread_mutex_lock(lock_); if (status != 0) { logger_error("pthread_mutex_lock error: %d", status); return false; } cond_count_++; status = acl_pthread_cond_signal(cond_); if (status != 0) { (void) acl_pthread_mutex_unlock(lock_); logger_error("pthread_cond_signal error: %d", status); return false; } status = acl_pthread_mutex_unlock(lock_); if (status != 0) { logger_error("pthread_mutex_unlock error: %d", status); return false; } return true; }
void hook_epoll(void) { static acl_pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER; static int __called = 0; (void) acl_pthread_mutex_lock(&__lock); if (__called) { (void) acl_pthread_mutex_unlock(&__lock); return; } __called++; __sys_epoll_create = (epoll_create_fn) dlsym(RTLD_NEXT, "epoll_create"); acl_assert(__sys_epoll_create); __sys_epoll_wait = (epoll_wait_fn) dlsym(RTLD_NEXT, "epoll_wait"); acl_assert(__sys_epoll_wait); __sys_epoll_ctl = (epoll_ctl_fn) dlsym(RTLD_NEXT, "epoll_ctl"); acl_assert(__sys_epoll_ctl); (void) acl_pthread_mutex_unlock(&__lock); }
void * acl_atomic_xchg(ACL_ATOMIC *self, void *value) { #ifndef HAS_ATOMIC void *old; acl_pthread_mutex_lock(&self->lock); old = self->value; self->value = value; acl_pthread_mutex_unlock(&self->lock); return old; #elif defined(ACL_WINDOWS) return InterlockedExchangePointer((volatile PVOID*)&self->value, value); #elif defined(ACL_LINUX) # if defined(__GNUC__) && (__GNUC__ >= 4) return __sync_lock_test_and_set(&self->value, value); # else (void) self; (void) value; acl_msg_error("%s(%d), %s: not support!", __FILE__, __LINE__, __FUNCTION__); return NULL; # endif #endif }
bool locker::lock() { #ifdef ACL_HAS_SPINLOCK if (spinlock_) { if (pthread_spin_lock(spinlock_) != 0) return false; } else #endif if (mutex_) { if (acl_pthread_mutex_lock(mutex_) != 0) return false; } if (fHandle_ == ACL_FILE_INVALID) return true; int operation = ACL_FLOCK_OP_EXCLUSIVE; if (acl_myflock(fHandle_, ACL_FLOCK_STYLE_FCNTL, operation) == 0) return true; if (mutex_) acl_assert(acl_pthread_mutex_unlock(mutex_) == 0); return false; }
static void run_thread(void *arg) { RUN_CTX *ctx = (RUN_CTX*) arg; acl_pthread_mutex_lock(&__mutex); acl_vstream_fprintf(ctx->fp, "hello world, hello world, hello world, hello world, i: %d\n", ctx->i); acl_pthread_mutex_unlock(&__mutex); acl_myfree(ctx); }
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); }
bool thread_mutex::lock(void) { int ret = acl_pthread_mutex_lock(mutex_); if (ret) { #ifdef ACL_UNIX acl_set_error(ret); logger_error("pthread_mutex_lock error %s", last_serror()); #endif return false; } return true; }
static DWORD WINAPI RunThreadWrap(LPVOID data) #endif { acl_pthread_t *thread = (acl_pthread_t *) data; void *return_arg; ACL_FIFO *tls_value_list_ptr = tls_value_list_get(); unsigned long *tid = 0; /* 只是为了避免与主线程的 h_thread->handle = handle 产生冲突 */ if (__thread_inited) acl_pthread_mutex_lock(&__thread_lock); if (__thread_inited) acl_pthread_mutex_unlock(&__thread_lock); thread->id = acl_pthread_self(); return_arg = (void*) thread->start_routine(thread->routine_arg); /* 释放由 acl_pthread_setspecific 添加的线程局部变量 */ while (1) { TLS_VALUE *tls_value = private_fifo_pop(tls_value_list_ptr); if (tls_value == NULL) break; if (tls_value->tls_key == NULL || tls_value->tls_key->destructor == NULL || tls_value->tls_key->key < 0 || tls_value->tls_key->key >= ACL_PTHREAD_KEYS_MAX) { acl_default_free(__FILE__, __LINE__, tls_value); continue; } tls_value->tls_key->destructor(tls_value->value); acl_default_free(__FILE__, __LINE__, tls_value); } private_fifo_free(tls_value_list_ptr, NULL); /* 如果线程创建时为分离方式则需要关闭线程句柄 */ if (thread->detached) { if (!CloseHandle(thread->handle)) { acl_msg_error("close handle error(%s)", acl_last_serror()); } } acl_default_free(__FILE__, __LINE__, thread); return (DWORD) return_arg; }
int acl_mbox_send(ACL_MBOX *mbox, void *msg) { int ret; acl_pthread_mutex_lock(mbox->lock); acl_ypipe_write(mbox->ypipe, msg); ret = acl_ypipe_flush(mbox->ypipe); acl_pthread_mutex_unlock(mbox->lock); if (ret == 0) return 0; mbox->nsend++; if (acl_vstream_writen(mbox->out, __key, sizeof(__key) - 1) == ACL_VSTREAM_EOF) { return -1; } else return 0; }
/* Restart one of the threads that are waiting on the condition variable */ int acl_pthread_cond_signal(acl_pthread_cond_t *cond) { const char *myname = "acl_pthread_cond_signal"; if (cond == NULL) { acl_msg_error("%s, %s(%d): input invalid", __FILE__, myname, __LINE__); return -1; } /* If there are waiting threads not already signalled, then * signal the condition and wait for the thread to respond. */ acl_pthread_mutex_lock(cond->lock); if (cond->waiting > cond->signals) { ++cond->signals; acl_sem_post(cond->wait_sem); acl_pthread_mutex_unlock(cond->lock); acl_sem_wait(cond->wait_done); } else acl_pthread_mutex_unlock(cond->lock); return 0; }
int acl_pthread_create(acl_pthread_t *thread, acl_pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { const char *myname = "acl_pthread_create"; acl_pthread_t *h_thread; HANDLE handle; unsigned long id, flag; if (thread == NULL) { acl_msg_error("%s, %s(%d): input invalid", __FILE__, myname, __LINE__); acl_set_error(ACL_EINVAL); return ACL_EINVAL; } acl_pthread_once(&__create_thread_control_once, acl_pthread_init_once); memset(thread, 0, sizeof(acl_pthread_t)); h_thread = acl_default_calloc(__FILE__, __LINE__, 1, sizeof(acl_pthread_t)); if (h_thread == NULL) { acl_msg_error("%s, %s(%d): calloc error(%s)", __FILE__, myname, __LINE__, acl_last_serror()); acl_set_error(ACL_ENOMEM); return ACL_ENOMEM; } if (attr != NULL) h_thread->detached = attr->detached; else h_thread->detached = 1; h_thread->start_routine = start_routine; h_thread->routine_arg = arg; if (__thread_inited) { acl_pthread_mutex_lock(&__thread_lock); flag = 0; } else flag = CREATE_SUSPENDED; #ifdef ACL_WIN32_STDC h_thread->handle = handle = (HANDLE) _beginthreadex(NULL, attr ? (unsigned int) attr->stacksize : 0, RunThreadWrap, (void *) h_thread, flag, &id); #else h_thread->handle = handle = CreateThread(NULL, attr ? attr->stacksize : 0,, RunThreadWrap, h_thread, flag, &id); #endif if (__thread_inited) acl_pthread_mutex_unlock(&__thread_lock); else if (flag == CREATE_SUSPENDED && handle != 0) ResumeThread(handle); if (handle == 0) { acl_msg_error("%s, %s(%d): CreateThread error(%s)", __FILE__, myname, __LINE__, acl_last_serror()); return -1; } thread->start_routine = start_routine; thread->routine_arg = arg; thread->id = id; thread->handle = 0; /* 根据线程的属性来确定线程创建时是分离模式还是非分离模式 */ if (attr == NULL || attr->detached) { thread->detached = 1; return 0; } thread->detached = 0; thread->handle = handle; return 0; }
bool rpc_request::cond_wait(int timeout /* = -1 */) { int status; status = acl_pthread_mutex_lock(lock_); if (status != 0) { logger_error("pthread_mutex_lock error: %d", status); return false; } if (--cond_count_ >= 0) { status = acl_pthread_mutex_unlock(lock_); if (status != 0) { logger_error("pthread_mutex_unlock error: %d", status); return false; } return true; } if (timeout < 0) { status = acl_pthread_cond_wait(cond_, lock_); if (status != 0) { logger_error("pthread_cond_wait error: %d", status); status = acl_pthread_mutex_unlock(lock_); if (status != 0) logger_error("pthread_mutex_unlock error: %d", status); return false; } status = acl_pthread_mutex_unlock(lock_); if (status != 0) { logger_error("pthread_mutex_unlock error: %d", status); return false; } return true; } struct timeval tv; struct timespec when_ttl; gettimeofday(&tv, NULL); when_ttl.tv_sec = tv.tv_sec + timeout / 1000; when_ttl.tv_nsec = tv.tv_usec * 1000 + (timeout % 1000) * 1000; wait_timedout_ = false; status = acl_pthread_cond_timedwait(cond_, lock_, &when_ttl); if (status != 0) { if (status == ACL_ETIMEDOUT) wait_timedout_ = true; else logger_error("pthread_cond_timedwait error: %d", status); status = acl_pthread_mutex_unlock(lock_); if (status != 0) logger_error("pthread_mutex_unlock error: %d", status); return false; } else { status = acl_pthread_mutex_unlock(lock_); if (status != 0) { logger_error("pthread_mutex_unlock error: %d", status); return false; } return true; } }
static void mempool_bench_test(const char *label, int mutex, int loop, acl_mem_type type, int size) { int i = 0; time_t begin = 0, end = 0; void *buf; #ifdef MUTEX_INIT acl_pthread_mutex_t lock; #elif defined(WIN32) acl_pthread_mutex_t lock; #define MUTEX_INIT #else acl_pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; #endif if (mutex) { #ifdef MUTEX_INIT acl_pthread_mutex_init(&lock, NULL); #endif time(&begin); while (i++ < loop) { acl_pthread_mutex_lock(&lock); acl_pthread_mutex_unlock(&lock); } time(&end); printf("lock and unkock, loop %d, time cost is %ld\r\n", loop, (long int) end - begin); i = 0; if (type > ACL_MEM_TYPE_NONE && type < ACL_MEM_TYPE_MAX) { time(&begin); while (i++ < loop) { acl_pthread_mutex_lock(&lock); buf = acl_allocator_mem_alloc(__var_allocator, type); acl_pthread_mutex_unlock(&lock); acl_pthread_mutex_lock(&lock); acl_allocator_mem_free(__var_allocator, type, buf); acl_pthread_mutex_unlock(&lock); } time(&end); } else if (type == MEM_TYPE_GROSS) { acl_pthread_mutex_lock(&lock); buf = acl_allocator_membuf_alloc(__FILE__, __LINE__, __var_allocator, size); acl_pthread_mutex_unlock(&lock); acl_pthread_mutex_lock(&lock); acl_allocator_membuf_free(__FILE__, __LINE__, __var_allocator, buf); acl_pthread_mutex_unlock(&lock); } else { time(&begin); while (i++ < loop) { acl_pthread_mutex_lock(&lock); buf = MALLOC(size); acl_pthread_mutex_unlock(&lock); acl_pthread_mutex_lock(&lock); FREE(buf); acl_pthread_mutex_unlock(&lock); } time(&end); } #ifdef MUTEX_INIT acl_pthread_mutex_destroy(&lock); #endif } else { if (type > ACL_MEM_TYPE_NONE && type < ACL_MEM_TYPE_MAX) { time(&begin); while (i++ < loop) { buf = acl_allocator_mem_alloc(__var_allocator, type); acl_allocator_mem_free(__var_allocator, type, buf); } time(&end); } else if (type == MEM_TYPE_GROSS) { buf = acl_allocator_membuf_alloc(__FILE__, __LINE__, __var_allocator, size); acl_allocator_membuf_free(__FILE__, __LINE__, __var_allocator, buf); } else { time(&begin); while (i++ < loop) { buf = MALLOC(size); FREE(buf); } time(&end); } } printf("%s: time cost is %ld seconds, count is %d\r\n", label, (long int) end - begin, loop); }
void hook_io(void) { static acl_pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER; static int __called = 0; (void) acl_pthread_mutex_lock(&__lock); if (__called) { (void) acl_pthread_mutex_unlock(&__lock); return; } __called++; __sys_sleep = (sleep_fn) dlsym(RTLD_NEXT, "sleep"); acl_assert(__sys_sleep); __sys_pipe = (pipe_fn) dlsym(RTLD_NEXT, "pipe"); acl_assert(__sys_pipe); #ifdef HAS_PIPE2 __sys_pipe2 = (pipe2_fn) dlsym(RTLD_NEXT, "pipe2"); acl_assert(__sys_pipe2); #endif __sys_popen = (popen_fn) dlsym(RTLD_NEXT, "popen"); acl_assert(__sys_popen); __sys_pclose = (pclose_fn) dlsym(RTLD_NEXT, "pclose"); acl_assert(__sys_pclose); __sys_close = (close_fn) dlsym(RTLD_NEXT, "close"); acl_assert(__sys_close); __sys_mkdir = (mkdir_fn) dlsym(RTLD_NEXT, "mkdir"); acl_assert(__sys_mkdir); __sys_stat = (stat_fn) dlsym(RTLD_NEXT, "__xstat"); acl_assert(__sys_stat); __sys_fstat = (fstat_fn) dlsym(RTLD_NEXT, "__fxstat"); acl_assert(__sys_fstat); __sys_read = (read_fn) dlsym(RTLD_NEXT, "read"); acl_assert(__sys_read); __sys_readv = (readv_fn) dlsym(RTLD_NEXT, "readv"); acl_assert(__sys_readv); __sys_recv = (recv_fn) dlsym(RTLD_NEXT, "recv"); acl_assert(__sys_recv); __sys_recvfrom = (recvfrom_fn) dlsym(RTLD_NEXT, "recvfrom"); acl_assert(__sys_recvfrom); __sys_recvmsg = (recvmsg_fn) dlsym(RTLD_NEXT, "recvmsg"); acl_assert(__sys_recvmsg); __sys_write = (write_fn) dlsym(RTLD_NEXT, "write"); acl_assert(__sys_write); __sys_writev = (writev_fn) dlsym(RTLD_NEXT, "writev"); acl_assert(__sys_writev); __sys_send = (send_fn) dlsym(RTLD_NEXT, "send"); acl_assert(__sys_send); __sys_sendto = (sendto_fn) dlsym(RTLD_NEXT, "sendto"); acl_assert(__sys_sendto); __sys_sendmsg = (sendmsg_fn) dlsym(RTLD_NEXT, "sendmsg"); acl_assert(__sys_sendmsg); #ifndef __USE_FILE_OFFSET64 __sys_sendfile = (sendfile_fn) dlsym(RTLD_NEXT, "sendfile"); acl_assert(__sys_sendfile); #endif #ifdef __USE_LARGEFILE64 __sys_sendfile64 = (sendfile64_fn) dlsym(RTLD_NEXT, "sendfile64"); acl_assert(__sys_sendfile64); #endif __sys_pread = (pread_fn) dlsym(RTLD_NEXT, "pread"); acl_assert(__sys_pread); __sys_pwrite = (pwrite_fn) dlsym(RTLD_NEXT, "pwrite"); acl_assert(__sys_pwrite); __sys_pread64 = (pread64_fn) dlsym(RTLD_NEXT, "pread64"); acl_assert(__sys_pread64); __sys_pwrite64 = (pwrite64_fn) dlsym(RTLD_NEXT, "pwrite64"); acl_assert(__sys_pwrite64); (void) acl_pthread_mutex_unlock(&__lock); }
/* Wait on the condition variable for at most 'ms' milliseconds. * The mutex must be locked before entering this function! * The mutex is unlocked during the wait, and locked again after the wait. Typical use: Thread A: pthread_mutex_lock(lock); while ( ! condition ) { SDL_CondWait(cond); } pthread_mutex_unlock(lock); Thread B: pthread_mutex_lock(lock); ... condition = true; ... pthread_mutex_unlock(lock); */ int acl_pthread_cond_timedwait(acl_pthread_cond_t *cond, acl_pthread_mutex_t *mutex, const struct timespec *timeout) { const char *myname = "acl_pthread_cond_timedwait"; int retval; if (cond == NULL) { acl_msg_error("%s, %s(%d): input invalid", __FILE__, myname, __LINE__); return -1; } /* Obtain the protection mutex, and increment the number of waiters. * This allows the signal mechanism to only perform a signal if there * are waiting threads. */ acl_pthread_mutex_lock(cond->lock); ++cond->waiting; acl_pthread_mutex_unlock(cond->lock); /* Unlock the mutex, as is required by condition variable semantics */ acl_pthread_mutex_unlock(mutex); /* Wait for a signal */ if (timeout == NULL) retval = acl_sem_wait(cond->wait_sem); else { int ms; struct timeval tv; gettimeofday(&tv, NULL); ms = (int) (timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000); ms -= tv.tv_sec * 1000 + tv.tv_usec / 1000; if (ms < 0) ms = 0; retval = acl_sem_wait_timeout(cond->wait_sem, (unsigned int) ms); } /* Let the signaler know we have completed the wait, otherwise * the signaler can race ahead and get the condition semaphore * if we are stopped between the mutex unlock and semaphore wait, * giving a deadlock. See the following URL for details: * http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html */ acl_pthread_mutex_lock(cond->lock); if (cond->signals > 0) { /* If we timed out, we need to eat a condition signal */ if (retval > 0) acl_sem_wait(cond->wait_sem); /* We always notify the signal thread that we are done */ acl_sem_post(cond->wait_done); /* Signal handshake complete */ --cond->signals; } --cond->waiting; acl_pthread_mutex_unlock(cond->lock); /* Lock the mutex, as is required by condition variable semantics */ acl_pthread_mutex_lock(mutex); return retval; }