X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvpp-api%2Fclient%2Fclient.c;h=542df9d414b6cb664d00266a22c2ff82b72c2443;hb=3459ece6da90627b161e2128b5926f1e58e7db65;hp=6a12c4ab963952f60fa4953b1a1a51e5a5a2a3f2;hpb=b7b929931a07fbb27b43d5cd105f366c3e29807e;p=vpp.git diff --git a/src/vpp-api/client/client.c b/src/vpp-api/client/client.c index 6a12c4ab963..542df9d414b 100644 --- a/src/vpp-api/client/client.c +++ b/src/vpp-api/client/client.c @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include #include #include @@ -29,12 +30,14 @@ #include #include -#include +#include +#include #include "vppapiclient.h" bool timeout_cancelled; bool timeout_in_progress; +bool rx_thread_done; /* * Asynchronous mode: @@ -46,17 +49,6 @@ bool timeout_in_progress; * vac_read() -> resumes RX thread */ -#define vl_typedefs /* define message structures */ -#include -#undef vl_typedefs - -#define vl_endianfun /* define message structures */ -#include -#undef vl_endianfun - -vlib_main_t vlib_global_main; -vlib_main_t **vlib_mains; - typedef struct { u8 connected_to_vlib; pthread_t rx_thread_handle; @@ -77,39 +69,8 @@ u16 read_timeout = 0; bool rx_is_running = false; bool timeout_thread_cancelled = false; -/* Set to true to enable memory tracing */ -bool mem_trace = false; - -__attribute__((constructor)) -static void -vac_client_constructor (void) -{ - clib_mem_init (0, 1 << 30); -#if USE_DLMALLOC == 0 - { - u8 *heap; - mheap_t *h; - - heap = clib_mem_get_per_cpu_heap (); - h = mheap_header (heap); - /* make the main heap thread-safe */ - h->flags |= MHEAP_FLAG_THREAD_SAFE; - } -#endif - if (mem_trace) - clib_mem_trace (1); -} - -__attribute__((destructor)) -static void -vac_client_destructor (void) -{ - if (mem_trace) - fformat(stderr, "TRACE: %s", - format (0, "%U\n", - format_mheap, clib_mem_get_heap (), 1)); -} - +/* Only ever allocate one heap */ +bool mem_initialized = false; static void init (void) @@ -176,7 +137,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; @@ -185,12 +146,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); @@ -234,7 +197,7 @@ 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; int rv; @@ -269,7 +232,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; @@ -303,24 +266,26 @@ 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); } int vac_connect (char * name, char * chroot_prefix, vac_callback_t cb, - int rx_qlen) + int rx_qlen) { + rx_thread_done = false; int rv = 0; vac_main_t *pm = &vac_main; + assert (clib_mem_get_heap ()); init(); if (chroot_prefix != NULL) vl_set_memory_root_path (chroot_prefix); @@ -386,9 +351,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; @@ -404,9 +370,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); @@ -423,7 +392,7 @@ vac_disconnect (void) vl_client_disconnect(); vl_client_api_unmap(); - vac_callback = 0; + //vac_callback = 0; cleanup(); @@ -434,7 +403,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; @@ -443,11 +412,15 @@ 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 VAC_NOT_CONNECTED; *l = 0; - if (am->our_pid == 0) return (-1); + /* svm_queue_sub(below) returns {-1, -2} */ + if (am->our_pid == 0) + return (VAC_SHM_NOT_READY); /* Poke timeout thread */ if (timeout) @@ -459,6 +432,7 @@ 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: @@ -478,7 +452,7 @@ vac_read (char **p, int *l, u16 timeout) 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... */ @@ -510,33 +484,35 @@ vac_read (char **p, int *l, u16 timeout) vl_msg_api_free((void *) msg); /* Client might forget to resume RX thread on failure */ vac_rx_resume (); - return -1; + return VAC_TIMEOUT; } /* * XXX: Makes the assumption that client_index is the first member */ -typedef VL_API_PACKED(struct _vl_api_header { +typedef struct _vl_api_header +{ u16 _vl_msg_id; u32 client_index; -}) vl_api_header_t; +} __attribute__ ((packed)) vl_api_header_t; 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; - if (!pm->connected_to_vlib) return -1; + if (!pm->connected_to_vlib) + return VAC_NOT_CONNECTED; if (!mp) return (-1); memcpy(mp, p, l); @@ -552,9 +528,9 @@ vac_write (char *p, int l) } int -vac_get_msg_index (unsigned char * name) +vac_get_msg_index (char * name) { - return vl_msg_api_get_msg_index (name); + return vl_msg_api_get_msg_index ((u8 *)name); } int @@ -575,5 +551,21 @@ vac_msg_table_max_index(void) void vac_set_error_handler (vac_error_callback_t cb) { + assert (clib_mem_get_heap ()); if (cb) clib_error_register_handler (cb, 0); } + +/* + * Required if application doesn't use a VPP heap. + */ +void +vac_mem_init (size_t size) +{ + if (mem_initialized) + return; + if (size == 0) + clib_mem_init (0, 1 << 30); // default + else + clib_mem_init (0, size); + mem_initialized = true; +}