APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond, apr_pool_t *pool) { apr_thread_cond_t *new_cond; sem_id rv; int i; new_cond = (apr_thread_cond_t *)apr_palloc(pool, sizeof(apr_thread_cond_t)); if (new_cond == NULL) return APR_ENOMEM; if ((rv = create_sem(1, "apr conditional lock")) < B_OK) return rv; new_cond->lock = rv; new_cond->pool = pool; APR_RING_INIT(&new_cond->alist, waiter_t, link); APR_RING_INIT(&new_cond->flist, waiter_t, link); for (i=0;i < 10 ;i++) { struct waiter_t *nw = make_waiter(pool); APR_RING_INSERT_TAIL(&new_cond->flist, nw, waiter_t, link); } apr_pool_cleanup_register(new_cond->pool, (void *)new_cond, thread_cond_cleanup, apr_pool_cleanup_null); *cond = new_cond; return APR_SUCCESS; }
static apr_status_t do_wait(apr_thread_cond_t *cond, apr_thread_mutex_t *mutex, apr_interval_time_t timeout) { struct waiter_t *wait; thread_id cth = find_thread(NULL); apr_status_t rv; int flags = B_RELATIVE_TIMEOUT; /* We must be the owner of the mutex or we can't do this... */ if (mutex->owner != cth) { /* What should we return??? */ return APR_EINVAL; } acquire_sem(cond->lock); wait = APR_RING_FIRST(&cond->flist); if (wait) APR_RING_REMOVE(wait, link); else wait = make_waiter(cond->pool); APR_RING_INSERT_TAIL(&cond->alist, wait, waiter_t, link); cond->condlock = mutex; release_sem(cond->lock); apr_thread_mutex_unlock(cond->condlock); if (timeout == 0) flags = 0; rv = acquire_sem_etc(wait->sem, 1, flags, timeout); apr_thread_mutex_lock(cond->condlock); if (rv != B_OK) { if (rv == B_TIMED_OUT) return APR_TIMEUP; return rv; } acquire_sem(cond->lock); APR_RING_REMOVE(wait, link); APR_RING_INSERT_TAIL(&cond->flist, wait, waiter_t, link); release_sem(cond->lock); return APR_SUCCESS; }