Beispiel #1
0
/** Initiate recognition based on specified grammar and input file */
ASR_CLIENT_DECLARE(apt_bool_t) asr_session_file_recognize(
									asr_session_t *asr_session, 
									const char *grammar_file, 
									const char *input_file)
{
	const mrcp_app_message_t *app_message;
	mrcp_message_t *mrcp_message;

	app_message = NULL;
	mrcp_message = define_grammar_message_create(asr_session,grammar_file);
	if(!mrcp_message) {
		apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create DEFINE-GRAMMAR Request");
		return FALSE;
	}

	/* Send DEFINE-GRAMMAR request and wait for the response */
	apr_thread_mutex_lock(asr_session->mutex);
	if(mrcp_application_message_send(asr_session->mrcp_session,asr_session->mrcp_channel,mrcp_message) == TRUE) {
		apr_thread_cond_wait(asr_session->wait_object,asr_session->mutex);
		app_message = asr_session->app_message;
		asr_session->app_message = NULL;
	}
	apr_thread_mutex_unlock(asr_session->mutex);

	if(mrcp_response_check(app_message,MRCP_REQUEST_STATE_COMPLETE) == FALSE) {
		return FALSE;
	}

	/* Reset prev recog result (if any) */
	asr_session->recog_complete = NULL;

	app_message = NULL;
	mrcp_message = recognize_message_create(asr_session);
	if(!mrcp_message) {
		apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create RECOGNIZE Request");
		return FALSE;
	}

	/* Send RECOGNIZE request and wait for the response */
	apr_thread_mutex_lock(asr_session->mutex);
	if(mrcp_application_message_send(asr_session->mrcp_session,asr_session->mrcp_channel,mrcp_message) == TRUE) {
		apr_thread_cond_wait(asr_session->wait_object,asr_session->mutex);
		app_message = asr_session->app_message;
		asr_session->app_message = NULL;
	}
	apr_thread_mutex_unlock(asr_session->mutex);

	if(mrcp_response_check(app_message,MRCP_REQUEST_STATE_INPROGRESS) == FALSE) {
		return FALSE;
	}
	
	/* Open input file and start streaming */
	asr_session->input_mode = INPUT_MODE_FILE;
	if(asr_input_file_open(asr_session,input_file) == FALSE) {
		return FALSE;
	}
	asr_session->streaming = TRUE;
  return TRUE;
}
void LLCondition::wait()
{
	if (AIThreadID::in_main_thread_inline())
	{
		LLFastTimer ft1(FT_WAIT_FOR_CONDITION);
		apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
	}
	else
	{
		apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
	}
}
Beispiel #3
0
op_generic_t *gop_waitany(op_generic_t *g)
{
    op_generic_t *gop = g;
    callback_t *cb;

    lock_gop(g);

    if (gop_get_type(g) == Q_TYPE_QUE) {
        log_printf(15, "sync_exec_que_check gid=%d stack_size=%d started_exec=%d\n", gop_id(g), stack_size(g->q->opque->qd.list), g->base.started_execution);
        if ((stack_size(g->q->opque->qd.list) == 1) && (g->base.started_execution == 0)) {  //** See if we can directly exec
            g->base.started_execution = 1;
            cb = (callback_t *)pop(g->q->opque->qd.list);
            gop = (op_generic_t *)cb->priv;
            log_printf(15, "sync_exec_que -- waiting for pgid=%d cgid=%d to complete\n", gop_id(g), gop_id(gop));
            unlock_gop(g);
            gop_waitany(gop);
            pop(g->q->finished); //** Remove it from the finished list.
            return(gop);
        } else {
            _gop_start_execution(g);  //** Make sure things have been submitted
            while (((gop = (op_generic_t *)pop(g->q->finished)) == NULL) && (g->q->nleft > 0)) {
                apr_thread_cond_wait(g->base.ctl->cond, g->base.ctl->lock); //** Sleep until something completes
            }
        }

        if (gop != NULL) log_printf(15, "POP finished qid=%d gid=%d\n", gop_id(g), gop_id(gop));
//log_printf(15, "Printing qid=%d finished stack\n", gop_id(g));
//_opque_print_stack(g->q->finished);
    } else {
        log_printf(15, "gop_waitany: BEFORE (type=op) While gid=%d state=%d\n", gop_id(g), g->base.state);
        flush_log();
        if ((g->base.pc->fn->sync_exec != NULL) && (g->base.started_execution == 0)) {  //** See if we can directly exec
            unlock_gop(g);  //** Don't need this for a direct exec
            log_printf(15, "sync_exec -- waiting for gid=%d to complete\n", gop_id(g));
            g->base.pc->fn->sync_exec(g->base.pc, g);
            log_printf(15, "sync_exec -- gid=%d completed with err=%d\n", gop_id(g), g->base.state);
            return(g);
        } else {  //** Got to submit it normally
            unlock_gop(g);  //** It's a single task so no need to hold the lock.  Otherwise we can deadlock
            _gop_start_execution(g);  //** Make sure things have been submitted
            lock_gop(g);  //** but we do need it for detecting when we're finished.
            while (g->base.state == 0) {
                apr_thread_cond_wait(g->base.ctl->cond, g->base.ctl->lock); //** Sleep until something completes
            }
        }
        log_printf(15, "gop_waitany: AFTER (type=op) While gid=%d state=%d\n", gop_id(g), g->base.state);
        flush_log();
    }
    unlock_gop(g);

    return(gop);
}
Beispiel #4
0
int gop_waitall(op_generic_t *g)
{
    int status;
    op_generic_t *g2;
    callback_t *cb;

//log_printf(15, "START gid=%d type=%d\n", gop_id(g), gop_get_type(g));
    log_printf(5, "START gid=%d type=%d\n", gop_id(g), gop_get_type(g));
    lock_gop(g);

    if (gop_get_type(g) == Q_TYPE_QUE) {
        log_printf(15, "sync_exec_que_check gid=%d stack_size=%d started_exec=%d\n", gop_id(g), stack_size(g->q->opque->qd.list), g->base.started_execution);

        if ((stack_size(g->q->opque->qd.list) == 1) && (g->base.started_execution == 0)) {  //** See if we can directly exec
            log_printf(15, "sync_exec_que -- waiting for gid=%d to complete\n", gop_id(g));
            cb = (callback_t *)pop(g->q->opque->qd.list);
            g2 = (op_generic_t *)cb->priv;
            unlock_gop(g);  //** Don't need this for a direct exec
            status = gop_waitall(g2);
            log_printf(15, "sync_exec -- gid=%d completed with err=%d\n", gop_id(g), status);
            return(status);
        } else {  //** Got to submit it normally
            _gop_start_execution(g);  //** Make sure things have been submitted
            while (g->q->nleft > 0) {
                apr_thread_cond_wait(g->base.ctl->cond, g->base.ctl->lock); //** Sleep until something completes
            }
        }
    } else {     //** Got a single task
        if ((g->base.pc->fn->sync_exec != NULL) && (g->base.started_execution == 0)) {  //** See if we can directly exec
            unlock_gop(g);  //** Don't need this for a direct exec
            log_printf(15, "sync_exec -- waiting for gid=%d to complete\n", gop_id(g));
            g->base.pc->fn->sync_exec(g->base.pc, g);
            status = _gop_completed_successfully(g);
            log_printf(15, "sync_exec -- gid=%d completed with err=%d\n", gop_id(g), status);
            return(status);
        } else {  //** Got to submit it the normal way
            _gop_start_execution(g);  //** Make sure things have been submitted
            while (g->base.state == 0) {
                log_printf(15, "gop_waitall: WHILE gid=%d state=%d\n", gop_id(g), g->base.state);
                apr_thread_cond_wait(g->base.ctl->cond, g->base.ctl->lock); //** Sleep until something completes
            }
        }
    }

    status = _gop_completed_successfully(g);

    log_printf(15, "END gid=%d type=%d\n", gop_id(g), gop_get_type(g));
    unlock_gop(g);

    return(status);
}
Beispiel #5
0
static void dynamic_binding(abts_case *tc, void *data)
{
    unsigned int i;
    apr_status_t rv;
    toolbox_t box[NTHREADS];
    apr_thread_t *thread[NTHREADS];
    apr_thread_mutex_t *mutex[NTHREADS];
    apr_thread_cond_t *cond = NULL;

    rv = apr_thread_cond_create(&cond, p);
    ABTS_SUCCESS(rv);
    ABTS_PTR_NOTNULL(tc, cond);

    for (i = 0; i < NTHREADS; i++) {
        rv = apr_thread_mutex_create(&mutex[i], APR_THREAD_MUTEX_DEFAULT, p);
        ABTS_SUCCESS(rv);

        rv = apr_thread_mutex_lock(mutex[i]);
        ABTS_SUCCESS(rv);

        box[i].tc = tc;
        box[i].cond = cond;
        box[i].mutex = mutex[i];
        box[i].func = lock_and_signal;

        rv = apr_thread_create(&thread[i], NULL, thread_routine, &box[i], p);
        ABTS_SUCCESS(rv);
    }

    /*
     * The dynamic binding should be preserved because we use only one waiter
     */

    for (i = 0; i < NTHREADS; i++) {
        rv = apr_thread_cond_wait(cond, mutex[i]);
        ABTS_SUCCESS(rv);
    }

    for (i = 0; i < NTHREADS; i++) {
        rv = apr_thread_cond_timedwait(cond, mutex[i], 10000);
        ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));

        rv = apr_thread_mutex_unlock(mutex[i]);
        ABTS_SUCCESS(rv);
    }

    for (i = 0; i < NTHREADS; i++) {
        apr_status_t retval;
        rv = apr_thread_join(&retval, thread[i]);
        ABTS_SUCCESS(rv);
    }

    rv = apr_thread_cond_destroy(cond);
    ABTS_SUCCESS(rv);

    for (i = 0; i < NTHREADS; i++) {
        rv = apr_thread_mutex_destroy(mutex[i]);
        ABTS_SUCCESS(rv);
    }
}
Beispiel #6
0
apr_status_t h2_mplx_in_read(h2_mplx *m, apr_read_type_e block,
                             int stream_id, apr_bucket_brigade *bb,
                             struct apr_thread_cond_t *iowait)
{
    apr_status_t status; 
    AP_DEBUG_ASSERT(m);
    if (m->aborted) {
        return APR_ECONNABORTED;
    }
    status = apr_thread_mutex_lock(m->lock);
    if (APR_SUCCESS == status) {
        h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
        if (io && !io->orphaned) {
            io->input_arrived = iowait;
            H2_MPLX_IO_IN(APLOG_TRACE2, m, io, "h2_mplx_in_read_pre");
            status = h2_io_in_read(io, bb, -1);
            while (APR_STATUS_IS_EAGAIN(status) 
                   && !is_aborted(m, &status)
                   && block == APR_BLOCK_READ) {
                apr_thread_cond_wait(io->input_arrived, m->lock);
                status = h2_io_in_read(io, bb, -1);
            }
            H2_MPLX_IO_IN(APLOG_TRACE2, m, io, "h2_mplx_in_read_post");
            io->input_arrived = NULL;
        }
        else {
            status = APR_EOF;
        }
        apr_thread_mutex_unlock(m->lock);
    }
    return status;
}
/** Destroy ASR session */
static apt_bool_t asr_session_destroy_ex(asr_session_t *asr_session, apt_bool_t terminate)
{
	if(terminate == TRUE) {
		apr_thread_mutex_lock(asr_session->mutex);
		if(mrcp_application_session_terminate(asr_session->mrcp_session) == TRUE) {
			apr_thread_cond_wait(asr_session->wait_object,asr_session->mutex);
			/* the response must be checked to be the valid one */
		}
		apr_thread_mutex_unlock(asr_session->mutex);
	}

	if(asr_session->audio_in) {
		fclose(asr_session->audio_in);
		asr_session->audio_in = NULL;
	}

	if(asr_session->mutex) {
		apr_thread_mutex_destroy(asr_session->mutex);
		asr_session->mutex = NULL;
	}
	if(asr_session->wait_object) {
		apr_thread_cond_destroy(asr_session->wait_object);
		asr_session->wait_object = NULL;
	}
	if(asr_session->media_buffer) {
		mpf_frame_buffer_destroy(asr_session->media_buffer);
		asr_session->media_buffer = NULL;
	}
	
	return mrcp_application_session_destroy(asr_session->mrcp_session);
}
Beispiel #8
0
static void pong(toolbox_t *box)
{
    apr_status_t rv;
    abts_case *tc = box->tc;

    rv = apr_thread_mutex_lock(box->mutex);
    ABTS_SUCCESS(rv);

    if (state == TOSS)
        state = PONG;

    do {
        rv = apr_thread_cond_signal(box->cond);
        ABTS_SUCCESS(rv);

        state = PING;

        rv = apr_thread_cond_wait(box->cond, box->mutex);
        ABTS_SUCCESS(rv);

        ABTS_TRUE(tc, state == PONG || state == OVER);
    } while (state != OVER);

    rv = apr_thread_mutex_unlock(box->mutex);
    ABTS_SUCCESS(rv);

    rv = apr_thread_cond_broadcast(box->cond);
    ABTS_SUCCESS(rv);
}
Beispiel #9
0
ZEKE_HIDDEN
apr_uint32_t
zktool_vxid_get(struct zktool_vxid_pool *vp)
{

  assert(vp != NULL && vp->magic == ZKTOOL_VXID_MAGIC);

  do {
    if(vp->count == 0) {
#ifdef ZEKE_USE_THREADS
      assert(apr_thread_mutex_lock(vp->mutex) == APR_SUCCESS);
      while(vp->busy > 0) {
        vp->waiter++;
        assert(apr_thread_cond_wait(vp-cond,vp->mutex) == APR_SUCCESS);
        vp->waiter--;
      }
      vp->busy++;
#endif
      vp->next = *VXID(vp).base;
      vp->count = *VXID(vp).chunk;
      *VXID(vp).chunk += vp->count;
#ifdef ZEKE_USE_THREADS
      vp->busy--
      assert(apr_thread_mutex_lock(vp->mutex) == APR_SUCCESS);
      if(vp->waiter)
        assert(apr_thread_cond_signal(vp->cond) == APR_SUCCESS);

      assert(apr_thread_mutex_unlock(vp->mutex) == APR_SUCCESS);
#endif
    }
    vp->count--;
    vp->next++;
  } while(vp->next == 0);
  return vp->next;
}
Beispiel #10
0
apr_status_t h2_mplx_in_read(h2_mplx *m, apr_read_type_e block,
                             int stream_id, apr_bucket_brigade *bb,
                             struct apr_thread_cond_t *iowait)
{
    apr_status_t status; 
    AP_DEBUG_ASSERT(m);
    if (m->aborted) {
        return APR_ECONNABORTED;
    }
    status = apr_thread_mutex_lock(m->lock);
    if (APR_SUCCESS == status) {
        h2_io *io = h2_io_set_get(m->stream_ios, stream_id);
        if (io) {
            io->input_arrived = iowait;
            status = h2_io_in_read(io, bb, 0);
            while (status == APR_EAGAIN 
                   && !is_aborted(m, &status)
                   && block == APR_BLOCK_READ) {
                apr_thread_cond_wait(io->input_arrived, m->lock);
                status = h2_io_in_read(io, bb, 0);
            }
            io->input_arrived = NULL;
        }
        else {
            status = APR_EOF;
        }
        apr_thread_mutex_unlock(m->lock);
    }
    return status;
}
Beispiel #11
0
apr_status_t h2_mplx_release_and_join(h2_mplx *m, apr_thread_cond_t *wait)
{
    apr_status_t status;
    
    workers_unregister(m);
    status = apr_thread_mutex_lock(m->lock);
    if (APR_SUCCESS == status) {
        while (!h2_io_set_iter(m->stream_ios, stream_done_iter, m)) {
            /* iterator until all h2_io have been orphaned or destroyed */
        }
    
        release(m, 0);
        while (m->refs > 0) {
            m->join_wait = wait;
            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c,
                          "h2_mplx(%ld): release_join, refs=%d, waiting...", 
                          m->id, m->refs);
            apr_thread_cond_wait(wait, m->lock);
        }
        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c,
                      "h2_mplx(%ld): release_join -> destroy, (#ios=%ld)", 
                      m->id, (long)h2_io_set_size(m->stream_ios));
        h2_mplx_destroy(m);
        /* all gone */
        /*apr_thread_mutex_unlock(m->lock);*/
    }
    return status;
}
Beispiel #12
0
void *monitor_thread(apr_thread_t *th, void *data)
{
    tbx_ns_monitor_t *nm = (tbx_ns_monitor_t *)data;
    tbx_ns_t *ns = nm->ns;
    int i;

    log_printf(15, "monitor_thread: Monitoring port %d\n", nm->port);

    apr_thread_mutex_lock(nm->lock);
    while (nm->shutdown_request == 0) {
        apr_thread_mutex_unlock(nm->lock);

        i = ns->connection_request(ns->sock, 1);

        if (i == 1) {  //** Got a request
            log_printf(15, "monitor_thread: port=%d ns=%d Got a connection request time=" TT "\n", nm->port, tbx_ns_getid(ns), apr_time_now());

            //** Mark that I have a connection pending
            apr_thread_mutex_lock(nm->lock);
            nm->is_pending = 1;
            apr_thread_mutex_unlock(nm->lock);

            //** Wake up the calling thread
            apr_thread_mutex_lock(nm->trigger_lock);
            (*(nm->trigger_count))++;
            apr_thread_cond_signal(nm->trigger_cond);
            apr_thread_mutex_unlock(nm->trigger_lock);

            log_printf(15, "monitor_thread: port=%d ns=%d waiting for accept\n", nm->port, tbx_ns_getid(ns));

            //** Sleep until my connection is accepted
            apr_thread_mutex_lock(nm->lock);
            while ((nm->is_pending == 1) && (nm->shutdown_request == 0)) {
                apr_thread_cond_wait(nm->cond, nm->lock);
                log_printf(15, "monitor_thread: port=%d ns=%d Cond triggered=" TT " trigger_count=%d\n", nm->port, tbx_ns_getid(ns), apr_time_now(), *(nm->trigger_count));
            }
            apr_thread_mutex_unlock(nm->lock);
            log_printf(15, "monitor_thread: port=%d ns=%d Connection accepted time=" TT "\n", nm->port, tbx_ns_getid(ns), apr_time_now());

            //** Update pending count
//         apr_thread_mutex_lock(nm->trigger_lock);
//         *(nm->trigger_count)--;
//         apr_thread_mutex_unlock(nm->trigger_lock);
        }

        apr_thread_mutex_lock(nm->lock);
    }

    apr_thread_mutex_unlock(nm->lock);

    //** Lastly shutdown my socket
    tbx_ns_close(ns);

    log_printf(15, "monitor_thread: Closing port %d\n", nm->port);

    apr_thread_exit(th, 0);

    return(NULL);
}
Beispiel #13
0
/**
 * Push new data onto the queue. Blocks if the queue is full. Once
 * the push operation has completed, it signals other threads waiting
 * in apr_queue_pop() that they may continue consuming sockets.
 * @param timeout added by Cisco. now uses apr_thread_cond_timewait(). 
 * interval of time to wait. zero means forever, negative indicates no wait, 
 * otherwise wait time in *microseconds*.
 * @return APR_SUCCESS, APR_EAGAIN, APR_EOF, APR_EINTR, APR_TIMEUP, 
 * or some APR error
 */
apr_status_t etch_apr_queue_push(etch_apr_queue_t *queue, 
                                 apr_interval_time_t timeout, 
                                 void *data)
{
    apr_status_t rv;

    if (queue->terminated)  
        rv = APR_EOF; /* no more elements ever again */
    else
    if (APR_SUCCESS == (rv = apr_thread_mutex_lock(queue->one_big_mutex)))
    {
        do 
        {   if (etch_apr_queue_full(queue)) 
            {
                if (!queue->terminated) 
                {
                    if (-1 == timeout) 
                    {   rv = APR_EAGAIN; /* asked to not wait */
                        break;
                    }

                    queue->full_waiters++;

                    if (0 == timeout)
                        rv = apr_thread_cond_wait(queue->not_full, queue->one_big_mutex);
                    else
                        rv = apr_thread_cond_timedwait(queue->not_full, queue->one_big_mutex, timeout);

                    queue->full_waiters--;
                    if (rv != APR_SUCCESS)  
                        break;
                }

                /* If we wake up and it's still empty, then we were interrupted */
                if (etch_apr_queue_full(queue)) 
                {
                    Q_DBG("queue full (intr)", queue);
                    rv = queue->terminated? APR_EOF: APR_EINTR; 
                    break;
                }
            }

            queue->data[queue->in] = data;
            queue->in = (queue->in + 1) % queue->bounds;
            queue->nelts++;

            if (queue->empty_waiters) 
            {
                Q_DBG("sig !empty", queue);
                rv = apr_thread_cond_signal(queue->not_empty);
            }

        } while(0);

        apr_thread_mutex_unlock(queue->one_big_mutex);
    }

    return rv;
}
Beispiel #14
0
op_status_t mqs_response_client_more(void *task_arg, int tid)
{
    mq_task_t *task = (mq_task_t *)task_arg;
    mq_stream_t *mqs = (mq_stream_t *)task->arg;
    op_status_t status = op_success_status;

    log_printf(5, "START msid=%d\n", mqs->msid);

    //** Parse the response
    mq_remove_header(task->response, 1);

    //** Wait for a notification that the data can be processed
    apr_thread_mutex_lock(mqs->lock);
    log_printf(5, "INIT STATUS msid=%d waiting=%d processed=%d\n", mqs->msid, mqs->waiting, mqs->processed);
    mqs->transfer_packets++;
    mqs->waiting = 0;
    apr_thread_cond_broadcast(mqs->cond);

    //** Now wait until the application is ready
    while (mqs->waiting == 0) {
        apr_thread_cond_wait(mqs->cond, mqs->lock);
    }

    //** Can accept the data
    mq_get_frame(mq_msg_first(task->response), (void **)&(mqs->data), &(mqs->len));
    pack_read_new_data(mqs->pack, &(mqs->data[MQS_HEADER]), mqs->len-MQS_HEADER);

    //** Notify the consumer it's available
    mqs->waiting = -2;
    apr_thread_cond_broadcast(mqs->cond);

    //** Wait until it's consumed
    while (mqs->processed == 0) {
        apr_thread_cond_wait(mqs->cond, mqs->lock);
    }

    mqs->data = NULL;    //** Nullify the data so it's not accidentally accessed
    mqs->processed = 0;  //** and reset the processed flag back to 0

    apr_thread_mutex_unlock(mqs->lock);

    log_printf(5, "END msid=%d status=%d %d\n", mqs->msid, status.op_status, status.error_code);

    return(status);
}
Beispiel #15
0
static apr_status_t wait_cond(h2_bucket_beam *beam, apr_thread_mutex_t *lock)
{
    if (beam->timeout > 0) {
        return apr_thread_cond_timedwait(beam->m_cond, lock, beam->timeout);
    }
    else {
        return apr_thread_cond_wait(beam->m_cond, lock);
    }
}
Beispiel #16
0
/**
 * Retrieves the next item from the queue. If there are no
 * items available, it will block until one becomes available.
 * Once retrieved, the item is placed into the address specified by
 * 'data'.
 */
APU_DECLARE(apr_status_t) apr_queue_pop(apr_queue_t *queue, void **data)
{
    apr_status_t rv;

    if (queue->terminated) {
        return APR_EOF; /* no more elements ever again */
    }

    rv = apr_thread_mutex_lock(queue->one_big_mutex);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    /* Keep waiting until we wake up and find that the queue is not empty. */
    if (apr_queue_empty(queue)) {
        if (!queue->terminated) {
            queue->empty_waiters++;
            rv = apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex);
            queue->empty_waiters--;
            if (rv != APR_SUCCESS) {
                apr_thread_mutex_unlock(queue->one_big_mutex);
                return rv;
            }
        }
        /* If we wake up and it's still empty, then we were interrupted */
        if (apr_queue_empty(queue)) {
            Q_DBG("queue empty (intr)", queue);
            rv = apr_thread_mutex_unlock(queue->one_big_mutex);
            if (rv != APR_SUCCESS) {
                return rv;
            }
            if (queue->terminated) {
                return APR_EOF; /* no more elements ever again */
            }
            else {
                return APR_EINTR;
            }
        }
    } 

    *data = queue->data[queue->out];
    queue->nelts--;

    queue->out = (queue->out + 1) % queue->bounds;
    if (queue->full_waiters) {
        Q_DBG("signal !full", queue);
        rv = apr_thread_cond_signal(queue->not_full);
        if (rv != APR_SUCCESS) {
            apr_thread_mutex_unlock(queue->one_big_mutex);
            return rv;
        }
    }

    rv = apr_thread_mutex_unlock(queue->one_big_mutex);
    return rv;
}
Beispiel #17
0
/**
 * Push new data onto the queue. Blocks if the queue is full. Once
 * the push operation has completed, it signals other threads waiting
 * in apr_queue_pop() that they may continue consuming sockets.
 */
APU_DECLARE(apr_status_t) apr_queue_push(apr_queue_t *queue, void *data)
{
    apr_status_t rv;

    if (queue->terminated) {
        return APR_EOF; /* no more elements ever again */
    }

    rv = apr_thread_mutex_lock(queue->one_big_mutex);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    if (apr_queue_full(queue)) {
        if (!queue->terminated) {
            queue->full_waiters++;
            rv = apr_thread_cond_wait(queue->not_full, queue->one_big_mutex);
            queue->full_waiters--;
            if (rv != APR_SUCCESS) {
                apr_thread_mutex_unlock(queue->one_big_mutex);
                return rv;
            }
        }
        /* If we wake up and it's still empty, then we were interrupted */
        if (apr_queue_full(queue)) {
            Q_DBG("queue full (intr)", queue);
            rv = apr_thread_mutex_unlock(queue->one_big_mutex);
            if (rv != APR_SUCCESS) {
                return rv;
            }
            if (queue->terminated) {
                return APR_EOF; /* no more elements ever again */
            }
            else {
                return APR_EINTR;
            }
        }
    }

    queue->data[queue->in] = data;
    queue->in = (queue->in + 1) % queue->bounds;
    queue->nelts++;

    if (queue->empty_waiters) {
        Q_DBG("sig !empty", queue);
        rv = apr_thread_cond_signal(queue->not_empty);
        if (rv != APR_SUCCESS) {
            apr_thread_mutex_unlock(queue->one_big_mutex);
            return rv;
        }
    }

    rv = apr_thread_mutex_unlock(queue->one_big_mutex);
    return rv;
}
Beispiel #18
0
/**
 * Retrieves the next available socket from the queue. If there are no
 * sockets available, it will block until one becomes available.
 * Once retrieved, the socket is placed into the address specified by
 * 'sd'.
 */
apr_status_t ap_queue_pop_something(fd_queue_t * queue, apr_socket_t ** sd,
                                    event_conn_state_t ** ecs, apr_pool_t ** p,
                                    timer_event_t ** te_out)
{
    fd_queue_elem_t *elem;
    apr_status_t rv;

    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
        return rv;
    }

    /* Keep waiting until we wake up and find that the queue is not empty. */
    if (ap_queue_empty(queue)) {
        if (!queue->terminated) {
            apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex);
        }
        /* If we wake up and it's still empty, then we were interrupted */
        if (ap_queue_empty(queue)) {
            rv = apr_thread_mutex_unlock(queue->one_big_mutex);
            if (rv != APR_SUCCESS) {
                return rv;
            }
            if (queue->terminated) {
                return APR_EOF; /* no more elements ever again */
            }
            else {
                return APR_EINTR;
            }
        }
    }

    *te_out = NULL;

    if (!APR_RING_EMPTY(&queue->timers, timer_event_t, link)) {
        *te_out = APR_RING_FIRST(&queue->timers);
        APR_RING_REMOVE(*te_out, link);
    }
    else {
        elem = &queue->data[queue->out];
        queue->out++;
        if (queue->out >= queue->bounds)
            queue->out -= queue->bounds;
        queue->nelts--;
        *sd = elem->sd;
        *ecs = elem->ecs;
        *p = elem->p;
#ifdef AP_DEBUG
        elem->sd = NULL;
        elem->p = NULL;
#endif /* AP_DEBUG */
    }

    rv = apr_thread_mutex_unlock(queue->one_big_mutex);
    return rv;
}
Beispiel #19
0
APU_DECLARE(apr_status_t) apr_reslist_acquire(apr_reslist_t *reslist,
                                              void **resource)
{
    apr_status_t rv;
    apr_res_t *res;

    apr_thread_mutex_lock(reslist->listlock);
    /* If there are idle resources on the available list, use
     * them right away. */
    if (reslist->nidle > 0) {
        /* Pop off the first resource */
        res = pop_resource(reslist);
        *resource = res->opaque;
        free_container(reslist, res);
        apr_thread_mutex_unlock(reslist->listlock);
        return APR_SUCCESS;
    }
    /* If we've hit our max, block until we're allowed to create
     * a new one, or something becomes free. */
    else while (reslist->ntotal >= reslist->hmax
                && reslist->nidle <= 0) {
        if (reslist->timeout) {
            if ((rv = apr_thread_cond_timedwait(reslist->avail, 
                reslist->listlock, reslist->timeout)) != APR_SUCCESS) {
                apr_thread_mutex_unlock(reslist->listlock);
                return rv;
            }
        }
        else
            apr_thread_cond_wait(reslist->avail, reslist->listlock);
    }
    /* If we popped out of the loop, first try to see if there
     * are new resources available for immediate use. */
    if (reslist->nidle > 0) {
        res = pop_resource(reslist);
        *resource = res->opaque;
        free_container(reslist, res);
        apr_thread_mutex_unlock(reslist->listlock);
        return APR_SUCCESS;
    }
    /* Otherwise the reason we dropped out of the loop
     * was because there is a new slot available, so create
     * a resource to fill the slot and use it. */
    else {
        rv = create_resource(reslist, &res);
        if (rv == APR_SUCCESS) {
            reslist->ntotal++;
            *resource = res->opaque;
        }
        free_container(reslist, res);
        apr_thread_mutex_unlock(reslist->listlock);
        return rv;
    }
}
Beispiel #20
0
ex_off_t _lru_force_free_mem(cache_t *c, segment_t *page_seg, ex_off_t bytes_to_free, int check_waiters)
{
    cache_segment_t *s = (cache_segment_t *)page_seg->priv;
    cache_lru_t *cp = (cache_lru_t *)c->fn.priv;
    ex_off_t freed_bytes, bytes_left;
    int top, finished;
    pigeon_coop_hole_t pch;
    cache_cond_t *cache_cond;

    //** I'm holding this coming in but don't need it cause I can touch all segs
    segment_unlock(page_seg);

    top = 0;
    bytes_left = bytes_to_free;
    freed_bytes = _lru_attempt_free_mem(c, page_seg, bytes_left);
    finished = 0;

    while ((freed_bytes < bytes_to_free) && (finished == 0)) {  //** Keep trying to mark space as free until I get enough
        if (top == 0) {
            top = 1;
            pch = reserve_pigeon_coop_hole(s->c->cond_coop);
            cache_cond = (cache_cond_t *)pigeon_coop_hole_data(&pch);
            cache_cond->count = 0;

            move_to_bottom(cp->pending_free_tasks);
            insert_below(cp->pending_free_tasks, cache_cond);  //** Add myself to the bottom
        } else {
            push(cp->pending_free_tasks, cache_cond);  //** I go on the top
        }

        log_printf(15, "not enough space so waiting cache_cond=%p freed_bytes=" XOT " bytes_to_free=" XOT "\n", cache_cond, freed_bytes, bytes_to_free);
        //** Now wait until it's my turn
        apr_thread_cond_wait(cache_cond->cond, c->lock);

        bytes_left -= freed_bytes;
        freed_bytes = _lru_attempt_free_mem(c, page_seg, bytes_left);
        finished = 1;
    }

    //** Now check if we can handle some waiters
    if (check_waiters == 1) _lru_process_waiters(c);

    cache_unlock(c);  //** Reacquire the lock in the proper order
    segment_lock(page_seg);  //** Reacquire the lock cause I had it coming in
    cache_lock(c);

    if (top == 1) release_pigeon_coop_hole(s->c->cond_coop, &pch);

    freed_bytes = bytes_to_free - bytes_left;
//NEW  freed_bytes = bytes_left - freed_bytes;

    return(freed_bytes);
}
Beispiel #21
0
static void * APR_THREAD_FUNC parser_thread(apr_thread_t *thread, void *data)
{
    apr_status_t status;
    apr_pool_t *pool, *subpool;
    parser_baton_t *ctx;

    ctx = (parser_baton_t*)data;
    pool = apr_thread_pool_get(thread);

    apr_pool_create(&subpool, pool);

    while (1) {
        doc_path_t *dup;

        apr_pool_clear(subpool);

        /* Grab it. */
        apr_thread_mutex_lock(ctx->mutex);
        /* Sleep. */
        apr_thread_cond_wait(ctx->condvar, ctx->mutex);

        /* Fetch the doc off the list. */
        if (ctx->doc_queue->nelts) {
            dup = *(doc_path_t**)(apr_array_pop(ctx->doc_queue));
            /* dup = (ctx->doc_queue->conns->elts)[0]; */
        }
        else {
            dup = NULL;
        }

        /* Don't need the mutex now. */
        apr_thread_mutex_unlock(ctx->mutex);

        /* Parse the doc/url pair. */
        if (dup) {
            status = find_href_doc(dup->doc, dup->path, ctx, subpool);
            if (status) {
                printf("Error finding hrefs: %d %s\n", status, dup->path);
            }
            /* Free the doc pair and its pool. */
            apr_pool_destroy(dup->pool);
            serf_bucket_mem_free(ctx->doc_queue_alloc, dup->path);
            serf_bucket_mem_free(ctx->doc_queue_alloc, dup);
        }

        /* Hey are we done? */
        if (!apr_atomic_read32(ctx->requests_outstanding)) {
            break;
        }
    }
    return NULL;
}
Beispiel #22
0
void LLCondition::wait()
{
	if (!isLocked())
	{ //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
		apr_thread_mutex_lock(mAPRMutexp);
#if MUTEX_DEBUG
		// avoid asserts on destruction in non-release builds
		U32 id = LLThread::currentID();
		mIsLocked[id] = TRUE;
#endif
	}
	apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
}
Beispiel #23
0
void _lru_wait_for_page(cache_t *c, segment_t *seg, int ontop)
{
    cache_lru_t *cp = (cache_lru_t *)c->fn.priv;
    cache_segment_t *s = (cache_segment_t *)seg->priv;
    lru_page_wait_t pw;
    pigeon_coop_hole_t pch;
    cache_cond_t *cc;
    ex_off_t bytes_free, bytes_needed, n;
    int check_waiters_first;

    check_waiters_first = (ontop == 0) ? 1 : 0;
    pch = reserve_pigeon_coop_hole(c->cond_coop);
    cc = (cache_cond_t *)pigeon_coop_hole_data(&pch);
    pw.cond = cc->cond;
    pw.bytes_needed = s->page_size;

    bytes_free = _lru_max_bytes(c) - cp->bytes_used;
    while (s->page_size > bytes_free) {
        //** Attempt to free pages
        bytes_needed = s->page_size - bytes_free;
        n = _lru_force_free_mem(c, seg, bytes_needed, check_waiters_first);

        if (n > 0) { //** Didn't make it so wait
            if (ontop == 0) {
                move_to_bottom(cp->waiting_stack);
                insert_below(cp->waiting_stack, &pw);
            } else {
                push(cp->waiting_stack, &pw);
            }

            segment_unlock(seg);  //** Unlock the segment to prevent deadlocks

            apr_thread_cond_wait(pw.cond, c->lock);  //** Wait for the space to become available

            //** Have to reaquire both locks in the correct order
            cache_unlock(c);
            segment_lock(seg);
            cache_lock(c);

            ontop = 1;  //** 2nd time we are always placed on the top of the stack
            check_waiters_first = 0;  //** And don't check on waiters
        }

        bytes_free = _lru_max_bytes(c) - cp->bytes_used;
    }

    release_pigeon_coop_hole(c->cond_coop, &pch);

    return;
}
static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data)
{
    int i;

    for (i = 0; i < MAX_COUNTER; i++) {
        apr_thread_mutex_lock(nready.mutex);
        while (nready.nready == 0)
            apr_thread_cond_wait(nready.cond, nready.mutex);
        nready.nready--;
        apr_thread_mutex_unlock(nready.mutex);

        if (buff[i] != i)
            printf("buff[%d] = %d\n", i, buff[i]);
    }

    return NULL;
}
Beispiel #25
0
static void nested_lock_and_wait(toolbox_t *box)
{
    apr_status_t rv;
    abts_case *tc = box->tc;

    rv = apr_thread_mutex_lock(box->mutex);
    ABTS_SUCCESS(rv);

    rv = apr_thread_mutex_lock(box->mutex);
    ABTS_SUCCESS(rv);

    rv = apr_thread_mutex_lock(box->mutex);
    ABTS_SUCCESS(rv);

    rv = apr_thread_cond_wait(box->cond, box->mutex);
    ABTS_SUCCESS(rv);
}
Beispiel #26
0
extern apr_status_t napr_threadpool_wait(napr_threadpool_t *threadpool)
{
    char errbuf[128];
    apr_status_t status;
    int list_size = 0;

    /* DEBUG_DBG("Called"); */
    if (APR_SUCCESS != (status = apr_thread_mutex_lock(threadpool->threadpool_mutex))) {
	DEBUG_ERR("error calling apr_thread_mutex_lock: %s", apr_strerror(status, errbuf, 128));
	return status;
    }
    list_size = napr_list_size(threadpool->list);
    if ((0 != list_size) || (threadpool->nb_waiting != threadpool->nb_thread)) {
	/* DEBUG_DBG("After lock before wait"); */
	/*
	 * Because the caller of this function has added all data we are now
	 * running, the line after, (cond_wait), make us wait to the end of
	 * processing.
	 */
	threadpool->run |= 0x1;

	if (APR_SUCCESS != (status = apr_thread_cond_wait(threadpool->threadpool_update, threadpool->threadpool_mutex))) {
	    DEBUG_ERR("error calling apr_thread_cond_wait: %s", apr_strerror(status, errbuf, 128));
	    return status;
	}
	/* DEBUG_DBG("Awake"); */
	/* Because all data have been processed, we are no more running  */
	threadpool->run &= 0x0;
    }
    /*
     * garbage collecting under lock protection to avoid list manipulation
     * during this freeing.
     * We are doing this garbage collecting because if not, we will re-using
     * the same pool to very-often alloc cell_t structures in list.
     * This could lead to a memory leak if not regularly cleaned.
     */
    napr_list_delete(threadpool->list);
    threadpool->list = napr_list_make(threadpool->pool);
    if (APR_SUCCESS != (status = apr_thread_mutex_unlock(threadpool->threadpool_mutex))) {
	DEBUG_ERR("error calling apr_thread_mutex_unlock: %s", apr_strerror(status, errbuf, 128));
	return status;
    }

    return APR_SUCCESS;
}
Beispiel #27
0
/**
 * Retrieves the next available socket from the queue. If there are no
 * sockets available, it will block until one becomes available.
 * Once retrieved, the socket is placed into the address specified by
 * 'sd'.
 */
apr_status_t ap_queue_pop(fd_queue_t *queue, apr_socket_t **sd, apr_pool_t **p)
{
    fd_queue_elem_t *elem;
    apr_status_t rv;

    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
        return rv;
    }

    /* Keep waiting until we wake up and find that the queue is not empty. */
    if (ap_queue_empty(queue)) {
        if (!queue->terminated) {
            apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex);
        }
        /* If we wake up and it's still empty, then we were interrupted */
        if (ap_queue_empty(queue)) {
            rv = apr_thread_mutex_unlock(queue->one_big_mutex);
            if (rv != APR_SUCCESS) {
                return rv;
            }
            if (queue->terminated) {
                return APR_EOF; /* no more elements ever again */
            }
            else {
                return APR_EINTR;
            }
        }
    }

    elem = &queue->data[queue->out];
    queue->out++;
    if (queue->out >= queue->bounds)
        queue->out -= queue->bounds;
    queue->nelts--;
    *sd = elem->sd;
    *p = elem->p;
#ifdef AP_DEBUG
    elem->sd = NULL;
    elem->p = NULL;
#endif /* AP_DEBUG */

    rv = apr_thread_mutex_unlock(queue->one_big_mutex);
    return rv;
}
Beispiel #28
0
static void lock_and_wait(toolbox_t *box)
{
    apr_status_t rv;
    abts_case *tc = box->tc;
    apr_uint32_t *count = box->data;

    rv = apr_thread_mutex_lock(box->mutex);
    ABTS_SUCCESS(rv);

    apr_atomic_inc32(count);

    rv = apr_thread_cond_wait(box->cond, box->mutex);
    ABTS_SUCCESS(rv);

    apr_atomic_dec32(count);

    rv = apr_thread_mutex_unlock(box->mutex);
    ABTS_SUCCESS(rv);
}
Beispiel #29
0
static void pipe_consumer(toolbox_t *box)
{
    char ch;
    apr_status_t rv;
    apr_size_t nbytes;
    abts_case *tc = box->tc;
    apr_file_t *out = box->data;
    apr_uint32_t consumed = 0;

    do {
        rv = apr_thread_mutex_lock(box->mutex);
        ABTS_SUCCESS(rv);

        while (!pipe_count && !exiting) {
            rv = apr_thread_cond_wait(box->cond, box->mutex);
            ABTS_SUCCESS(rv);
        }

        if (!pipe_count && exiting) {
            rv = apr_thread_mutex_unlock(box->mutex);
            ABTS_SUCCESS(rv);
            break;
        }

        pipe_count--;
        consumed++;

        rv = apr_thread_mutex_unlock(box->mutex);
        ABTS_SUCCESS(rv);

        rv = apr_file_read_full(out, &ch, 1, &nbytes);
        ABTS_SUCCESS(rv);
        ABTS_SIZE_EQUAL(tc, 1, nbytes);
        ABTS_TRUE(tc, ch == '.');
    } while (1);

    /* naive fairness test - it would be good to introduce or solidify
     * a solid test to ensure one thread is not starved.
     * ABTS_INT_EQUAL(tc, 1, !!consumed);
     */
}
Beispiel #30
0
void *gd_thread_func(apr_thread_t *th, void *data)
{
    op_generic_t *gop;

    apr_thread_mutex_lock(gd_lock);
    while (gd_shutdown == 0) {
        //** Execute everything on the stack
        while ((gop = (op_generic_t *)pop(gd_stack)) != NULL) {
            log_printf(15, "DUMMY gid=%d status=%d\n", gop_id(gop), gop->base.status.op_status);
            apr_thread_mutex_unlock(gd_lock);
            gop_mark_completed(gop, gop->base.status);
            apr_thread_mutex_lock(gd_lock);
        }

        //** Wait for more work
        apr_thread_cond_wait(gd_cond, gd_lock);
    }
    apr_thread_mutex_unlock(gd_lock);

    return(NULL);
}