vce_event_t *
vce_get_event_from_index(vce_event_thread_t *evt, u32 ev_idx)
{
- vce_event_t *ev;
+ vce_event_t *ev = 0;
clib_spinlock_lock (&(evt->events_lockp));
- ev = pool_elt_at_index (evt->vce_events, ev_idx);
+ if ( ! pool_is_free_index (evt->vce_events, ev_idx))
+ ev = pool_elt_at_index (evt->vce_events, ev_idx);
clib_spinlock_unlock (&(evt->events_lockp));
return ev;
-
}
vce_event_handler_reg_t *
vce_event_handler_reg_t *old_handler = 0;
uword *p;
u32 handler_index;
- u64 adj_key;
/* TODO - multiple handler support. For now we can replace
* and re-instate, which is useful for event recycling */
- adj_key = evk->as_u64 | (1LL << 63); //evk can be 0, which won't hash
-
clib_spinlock_lock (&evt->handlers_lockp);
- p = hash_get (evt->handlers_index_by_event_key, adj_key);
+ p = hash_get (evt->handlers_index_by_event_key, evk->as_u64);
if (p)
{
old_handler = pool_elt_at_index (evt->vce_event_handlers, p[0]);
handler->handler_fn = cb;
handler->replaced_handler_idx = (p) ? p[0] : ~0;
+ handler->ev_idx = ~0; //This will be set by the event thread if event happens
+ handler->evk = evk->as_u64;
- hash_set (evt->handlers_index_by_event_key, adj_key, handler_index);
+ hash_set (evt->handlers_index_by_event_key, evk->as_u64, handler_index);
pthread_cond_init (&(handler->handler_cond), NULL);
pthread_mutex_init (&(handler->handler_lock), NULL);
}
int
-vce_unregister_handler (vce_event_thread_t *evt, vce_event_t *ev)
+vce_unregister_handler (vce_event_thread_t *evt,
+ vce_event_handler_reg_t *handler)
{
- vce_event_handler_reg_t *handler;
uword *p;
- u64 adj_key = ev->evk.as_u64 | (1LL << 63);
+ u64 evk = handler->evk;
u8 generate_signal = 0;
clib_spinlock_lock (&evt->handlers_lockp);
- p = hash_get (evt->handlers_index_by_event_key, adj_key);
+ p = hash_get (evt->handlers_index_by_event_key, evk);
if (!p)
{
clib_spinlock_unlock (&evt->handlers_lockp);
-
return VNET_API_ERROR_NO_SUCH_ENTRY;
}
/* If this handler replaced another handler, re-instate it */
if (handler->replaced_handler_idx != ~0)
{
- hash_set (evt->handlers_index_by_event_key, adj_key,
+ hash_set (evt->handlers_index_by_event_key, evk,
handler->replaced_handler_idx);
generate_signal = 1;
}
else
{
- hash_unset (evt->handlers_index_by_event_key, adj_key);
+ hash_unset (evt->handlers_index_by_event_key, evk);
}
pthread_mutex_destroy (&(handler->handler_lock));
u32 ev_idx;
vce_event_handler_reg_t *handler;
uword *p;
- u64 adj_key;
evt->recycle_event = 1; // Used for recycling events with no handlers
clib_spinlock_unlock (&(evt->events_lockp));
ASSERT(ev);
- adj_key = ev->evk.as_u64 | (1LL << 63);
clib_spinlock_lock (&evt->handlers_lockp);
- p = hash_get (evt->handlers_index_by_event_key, adj_key);
+ p = hash_get (evt->handlers_index_by_event_key, ev->evk.as_u64);
if (!p)
{
/* If an event falls in the woods, and there is no handler to hear it,
/* VPPCOM Event typedefs */
typedef enum vcl_event_id_
{
+ VCL_EVENT_INVALID_EVENT,
VCL_EVENT_CONNECT_REQ_ACCEPTED,
VCL_EVENT_N_EVENTS
} vcl_event_id_t;
typedef struct vce_event_connect_request_
{
- u8 size;
- u8 handled;
u32 accepted_session_index;
} vce_event_connect_request_t;
{
u8 init;
u32 debug;
- u32 *client_session_index_fifo;
int main_cpu;
+ /* FIFO for accepted connections - used in epoll/select */
+ clib_spinlock_t session_fifo_lockp;
+ u32 *client_session_index_fifo;
+
/* vpp input queue */
svm_queue_t *vl_input_queue;
/* API client handle */
u32 my_client_index;
-
/* Session pool */
clib_spinlock_t sessions_lockp;
session_t *sessions;
{
vce_event_handler_reg_t *reg = (vce_event_handler_reg_t *) arg;
- vce_event_connect_request_t *ecr;
- vce_event_t *ev;
-
- ev = vce_get_event_from_index (&vcm->event_thread, reg->ev_idx);
-
- ecr = (vce_event_connect_request_t *) ev->data;
-
pthread_mutex_lock (®->handler_lock);
- ecr->handled = 1;
pthread_cond_signal (®->handler_cond);
pthread_mutex_unlock (®->handler_lock);
}
vce_event_connect_request_t *ecr = (vce_event_connect_request_t *) ev->data;
/* Add the accepted_session_index to the FIFO */
- clib_spinlock_lock (&vcm->sessions_lockp);
+ clib_spinlock_lock (&vcm->session_fifo_lockp);
clib_fifo_add1 (vcm->client_session_index_fifo,
ecr->accepted_session_index);
- clib_spinlock_unlock (&vcm->sessions_lockp);
+ clib_spinlock_unlock (&vcm->session_fifo_lockp);
/* Recycling the event. */
clib_spinlock_lock (&(vcm->event_thread.events_lockp));
vce_event_t *ev;
int rv;
u32 ev_idx;
-
+ uword elts = 0;
clib_spinlock_lock (&vcm->sessions_lockp);
- if (!clib_fifo_free_elts (vcm->client_session_index_fifo))
+
+ clib_spinlock_lock (&vcm->session_fifo_lockp);
+ elts = clib_fifo_free_elts (vcm->client_session_index_fifo);
+ clib_spinlock_unlock (&vcm->session_fifo_lockp);
+
+ if (!elts)
{
clib_warning ("VCL<%d>: client session queue is full!", getpid ());
vppcom_send_accept_session_reply (mp->handle, mp->context,
ev->evk.eid = VCL_EVENT_CONNECT_REQ_ACCEPTED;
listen_session = vppcom_session_table_lookup_listener (mp->listener_handle);
ev->evk.session_index = (u32) (listen_session - vcm->sessions);
- ecr->handled = 0;
ecr->accepted_session_index = session_index;
clib_spinlock_unlock (&vcm->event_thread.events_lockp);
clib_warning ("ip6");
}
}
+
clib_spinlock_unlock (&vcm->sessions_lockp);
}
conf_fname = VPPCOM_CONF_DEFAULT;
vppcom_cfg_heapsize (conf_fname);
vcl_cfg = &vcm->cfg;
+ clib_spinlock_init (&vcm->session_fifo_lockp);
clib_fifo_validate (vcm->client_session_index_fifo,
vcm->cfg.listen_queue_size);
vppcom_cfg_read (conf_fname);
goto done;
}
+ clib_spinlock_lock (&vcm->session_fifo_lockp);
clib_fifo_validate (vcm->client_session_index_fifo, q_len);
+ clib_spinlock_unlock (&vcm->session_fifo_lockp);
+
clib_spinlock_unlock (&vcm->sessions_lockp);
+
done:
return rv;
}
evk.eid = VCL_EVENT_CONNECT_REQ_ACCEPTED;
reg = vce_register_handler (&vcm->event_thread, &evk,
vce_connect_request_handler_fn);
- ev = vce_get_event_from_index (&vcm->event_thread, reg->ev_idx);
- result = (vce_event_connect_request_t *) ev->data;
+ ev = 0;
pthread_mutex_lock (®->handler_lock);
- while (!result->handled)
+ while (!ev)
{
rv =
pthread_cond_timedwait (®->handler_cond, ®->handler_lock, &ts);
rv = VPPCOM_EAGAIN;
goto cleanup;
}
+ ev = vce_get_event_from_index (&vcm->event_thread, reg->ev_idx);
}
+ result = (vce_event_connect_request_t *) ev->data;
client_session_index = result->accepted_session_index;
/* Remove from the FIFO used to service epoll */
- clib_spinlock_lock (&vcm->sessions_lockp);
+ clib_spinlock_lock (&vcm->session_fifo_lockp);
if (clib_fifo_elts (vcm->client_session_index_fifo))
{
u32 tmp_client_session_index;
clib_fifo_sub1 (vcm->client_session_index_fifo,
tmp_client_session_index);
+ /* It wasn't ours... put it back ... */
if (tmp_client_session_index != client_session_index)
clib_fifo_add1 (vcm->client_session_index_fifo,
tmp_client_session_index);
}
- clib_spinlock_unlock (&vcm->sessions_lockp);
+ clib_spinlock_unlock (&vcm->session_fifo_lockp);
+
+ clib_spinlock_lock (&vcm->sessions_lockp);
rv = vppcom_session_at_index (client_session_index, &client_session);
if (PREDICT_FALSE (rv))
}
clib_spinlock_unlock (&vcm->sessions_lockp);
- rv = (int) client_session_index;
+ rv = (int) client_session_index;
vce_clear_event (&vcm->event_thread, ev);
+
cleanup:
- vce_unregister_handler (&vcm->event_thread, ev);
+ vce_unregister_handler (&vcm->event_thread, reg);
pthread_mutex_unlock (®->handler_lock);
+
done:
return rv;
}
if (session->state & STATE_LISTEN)
{
+ clib_spinlock_lock (&vcm->session_fifo_lockp);
ready = clib_fifo_elts (vcm->client_session_index_fifo);
+ clib_spinlock_unlock (&vcm->session_fifo_lockp);
}
else
{
{
session_t *vep_session;
session_t *session;
- vce_event_t *ev = 0;
int rv;
if (vep_idx == session_index)
/* VCL Event Un-register handler */
if ((session->state & STATE_LISTEN) && vep_session->poll_reg)
{
- ev = vce_get_event_from_index (&vcm->event_thread,
- vep_session->poll_reg->ev_idx);
- (void) vce_unregister_handler (&vcm->event_thread, ev);
+ (void) vce_unregister_handler (&vcm->event_thread,
+ vep_session->poll_reg);
}
vep_session->wait_cont_idx =