X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvpp-api%2Fclient%2Fclient.c;h=057909514d85844bb9e440cb5a3c7e5437e2b2e8;hb=39d69112fcec114fde34955ceb41555221d3ba11;hp=68269bb9b5504e98fa3703cc6a8b67ae08f39584;hpb=94495f2a6a68ac2202b7715ce09620f1ba6fe673;p=vpp.git diff --git a/src/vpp-api/client/client.c b/src/vpp-api/client/client.c index 68269bb9b55..057909514d8 100644 --- a/src/vpp-api/client/client.c +++ b/src/vpp-api/client/client.c @@ -33,6 +33,10 @@ #include "vppapiclient.h" +bool timeout_cancelled; +bool timeout_in_progress; +bool rx_thread_done; + /* * Asynchronous mode: * Client registers a callback. All messages are sent to the callback. @@ -112,7 +116,7 @@ static void init (void) { vac_main_t *pm = &vac_main; - memset(pm, 0, sizeof(*pm)); + clib_memset(pm, 0, sizeof(*pm)); pthread_mutex_init(&pm->queue_lock, NULL); pthread_cond_init(&pm->suspend_cv, NULL); pthread_cond_init(&pm->resume_cv, NULL); @@ -134,7 +138,7 @@ cleanup (void) pthread_cond_destroy(&pm->timeout_cv); pthread_cond_destroy(&pm->timeout_cancel_cv); pthread_cond_destroy(&pm->terminate_cv); - memset(pm, 0, sizeof(*pm)); + clib_memset(pm, 0, sizeof(*pm)); } /* @@ -173,7 +177,7 @@ vac_rx_thread_fn (void *arg) vl_api_memclnt_keepalive_t *mp; vl_api_memclnt_keepalive_reply_t *rmp; vac_main_t *pm = &vac_main; - api_main_t *am = &api_main; + api_main_t *am = vlibapi_get_main(); vl_shmem_hdr_t *shmem_hdr; uword msg; @@ -182,12 +186,14 @@ vac_rx_thread_fn (void *arg) while (1) while (!svm_queue_sub(q, (u8 *)&msg, SVM_Q_WAIT, 0)) { + VL_MSG_API_UNPOISON((void *)msg); u16 id = ntohs(*((u16 *)msg)); switch (id) { case VL_API_RX_THREAD_EXIT: vl_msg_api_free((void *) msg); /* signal waiting threads that this thread is about to terminate */ pthread_mutex_lock(&pm->queue_lock); + rx_thread_done = true; pthread_cond_signal(&pm->terminate_cv); pthread_mutex_unlock(&pm->queue_lock); pthread_exit(0); @@ -212,7 +218,7 @@ vac_rx_thread_fn (void *arg) case VL_API_MEMCLNT_KEEPALIVE: mp = (void *)msg; rmp = vl_msg_api_alloc (sizeof (*rmp)); - memset (rmp, 0, sizeof (*rmp)); + clib_memset (rmp, 0, sizeof (*rmp)); rmp->_vl_msg_id = ntohs(VL_API_MEMCLNT_KEEPALIVE_REPLY); rmp->context = mp->context; shmem_hdr = am->shmem_hdr; @@ -231,30 +237,34 @@ vac_timeout_thread_fn (void *arg) { vl_api_memclnt_read_timeout_t *ep; vac_main_t *pm = &vac_main; - api_main_t *am = &api_main; + api_main_t *am = vlibapi_get_main(); struct timespec ts; struct timeval tv; - u16 timeout; int rv; while (pm->timeout_loop) { /* Wait for poke */ pthread_mutex_lock(&pm->timeout_lock); - pthread_cond_wait (&pm->timeout_cv, &pm->timeout_lock); - timeout = read_timeout; + while (!timeout_in_progress) + pthread_cond_wait (&pm->timeout_cv, &pm->timeout_lock); + + /* Starting timer */ gettimeofday(&tv, NULL); - ts.tv_sec = tv.tv_sec + timeout; + ts.tv_sec = tv.tv_sec + read_timeout; ts.tv_nsec = 0; - rv = pthread_cond_timedwait (&pm->timeout_cancel_cv, - &pm->timeout_lock, &ts); - pthread_mutex_unlock(&pm->timeout_lock); - if (rv == ETIMEDOUT && !timeout_thread_cancelled) - { + + if (!timeout_cancelled) { + rv = pthread_cond_timedwait (&pm->timeout_cancel_cv, + &pm->timeout_lock, &ts); + if (rv == ETIMEDOUT && !timeout_thread_cancelled) { ep = vl_msg_api_alloc (sizeof (*ep)); ep->_vl_msg_id = ntohs(VL_API_MEMCLNT_READ_TIMEOUT); vl_msg_api_send_shmem(am->vl_input_queue, (u8 *)&ep); } + } + + pthread_mutex_unlock(&pm->timeout_lock); } pthread_exit(0); } @@ -262,7 +272,7 @@ vac_timeout_thread_fn (void *arg) void vac_rx_suspend (void) { - api_main_t *am = &api_main; + api_main_t *am = vlibapi_get_main(); vac_main_t *pm = &vac_main; vl_api_memclnt_rx_thread_suspend_t *ep; @@ -296,14 +306,14 @@ vac_rx_resume (void) static uword * vac_msg_table_get_hash (void) { - api_main_t *am = &api_main; + api_main_t *am = vlibapi_get_main(); return (am->msg_index_by_name_and_crc); } int vac_msg_table_size(void) { - api_main_t *am = &api_main; + api_main_t *am = vlibapi_get_main(); return hash_elts(am->msg_index_by_name_and_crc); } @@ -311,6 +321,7 @@ int vac_connect (char * name, char * chroot_prefix, vac_callback_t cb, int rx_qlen) { + rx_thread_done = false; int rv = 0; vac_main_t *pm = &vac_main; @@ -353,13 +364,14 @@ vac_connect (char * name, char * chroot_prefix, vac_callback_t cb, return (0); } - static void set_timeout (unsigned short timeout) { vac_main_t *pm = &vac_main; pthread_mutex_lock(&pm->timeout_lock); read_timeout = timeout; + timeout_in_progress = true; + timeout_cancelled = false; pthread_cond_signal(&pm->timeout_cv); pthread_mutex_unlock(&pm->timeout_lock); } @@ -369,6 +381,8 @@ unset_timeout (void) { vac_main_t *pm = &vac_main; pthread_mutex_lock(&pm->timeout_lock); + timeout_in_progress = false; + timeout_cancelled = true; pthread_cond_signal(&pm->timeout_cancel_cv); pthread_mutex_unlock(&pm->timeout_lock); } @@ -376,9 +390,10 @@ unset_timeout (void) int vac_disconnect (void) { - api_main_t *am = &api_main; + api_main_t *am = vlibapi_get_main(); vac_main_t *pm = &vac_main; uword junk; + int rv = 0; if (!pm->connected_to_vlib) return 0; @@ -394,9 +409,12 @@ vac_disconnect (void) gettimeofday(&tv, NULL); ts.tv_sec = tv.tv_sec + 5; ts.tv_nsec = 0; + pthread_mutex_lock(&pm->queue_lock); - int rv = pthread_cond_timedwait(&pm->terminate_cv, &pm->queue_lock, &ts); + if (rx_thread_done == false) + rv = pthread_cond_timedwait(&pm->terminate_cv, &pm->queue_lock, &ts); pthread_mutex_unlock(&pm->queue_lock); + /* now join so we wait until thread has -really- finished */ if (rv == ETIMEDOUT) pthread_cancel(pm->rx_thread_handle); @@ -424,7 +442,7 @@ int vac_read (char **p, int *l, u16 timeout) { svm_queue_t *q; - api_main_t *am = &api_main; + api_main_t *am = vlibapi_get_main(); vac_main_t *pm = &vac_main; vl_api_memclnt_keepalive_t *mp; vl_api_memclnt_keepalive_reply_t *rmp; @@ -433,11 +451,13 @@ vac_read (char **p, int *l, u16 timeout) int rv; vl_shmem_hdr_t *shmem_hdr; - if (!pm->connected_to_vlib) return -1; + /* svm_queue_sub(below) returns {-1, -2} */ + if (!pm->connected_to_vlib) return -3; *l = 0; - if (am->our_pid == 0) return (-1); + /* svm_queue_sub(below) returns {-1, -2} */ + if (am->our_pid == 0) return (-4); /* Poke timeout thread */ if (timeout) @@ -449,11 +469,12 @@ vac_read (char **p, int *l, u16 timeout) rv = svm_queue_sub(q, (u8 *)&msg, SVM_Q_WAIT, 0); if (rv == 0) { + VL_MSG_API_UNPOISON((void *)msg); u16 msg_id = ntohs(*((u16 *)msg)); switch (msg_id) { case VL_API_RX_THREAD_EXIT: vl_msg_api_free((void *) msg); - return -1; + goto error; case VL_API_MEMCLNT_RX_THREAD_SUSPEND: goto error; case VL_API_MEMCLNT_READ_TIMEOUT: @@ -462,13 +483,13 @@ vac_read (char **p, int *l, u16 timeout) /* Handle an alive-check ping from vpp. */ mp = (void *)msg; rmp = vl_msg_api_alloc (sizeof (*rmp)); - memset (rmp, 0, sizeof (*rmp)); + clib_memset (rmp, 0, sizeof (*rmp)); rmp->_vl_msg_id = ntohs(VL_API_MEMCLNT_KEEPALIVE_REPLY); rmp->context = mp->context; shmem_hdr = am->shmem_hdr; vl_msg_api_send_shmem(shmem_hdr->vl_input_queue, (u8 *)&rmp); vl_msg_api_free((void *) msg); - /* + /* * Python code is blissfully unaware of these pings, so * act as if it never happened... */ @@ -484,15 +505,19 @@ vac_read (char **p, int *l, u16 timeout) } *p = (char *)msg; - /* Let timeout notification thread know we're done */ - unset_timeout(); } else { fprintf(stderr, "Read failed with %d\n", rv); } + /* Let timeout notification thread know we're done */ + if (timeout) + unset_timeout(); + return (rv); error: + if (timeout) + unset_timeout(); vl_msg_api_free((void *) msg); /* Client might forget to resume RX thread on failure */ vac_rx_resume (); @@ -510,14 +535,14 @@ typedef VL_API_PACKED(struct _vl_api_header { static u32 vac_client_index (void) { - return (api_main.my_client_index); + return (vlibapi_get_main()->my_client_index); } int vac_write (char *p, int l) { int rv = -1; - api_main_t *am = &api_main; + api_main_t *am = vlibapi_get_main(); vl_api_header_t *mp = vl_msg_api_alloc(l); svm_queue_t *q; vac_main_t *pm = &vac_main;