summaryrefslogtreecommitdiffstats
path: root/src/vpp-api/client
diff options
context:
space:
mode:
authorOle Troan <ot@cisco.com>2018-10-08 11:24:22 +0200
committerOle Trøan <otroan@employees.org>2018-10-09 07:23:29 +0000
commitde728ac3c06531f5c16fac65c505f0e63948ebe8 (patch)
tree73bd061fe49825d7cc869698ca75ca2670b478cb /src/vpp-api/client
parent20e6d36bca61dc004131d9be5385c71f8553e1fc (diff)
API: Spurious timeouts from timeout thread.
Change-Id: I1be1101ba4d82688a32b5ae2c39ca5d92dc244b7 Signed-off-by: Ole Troan <ot@cisco.com>
Diffstat (limited to 'src/vpp-api/client')
-rw-r--r--src/vpp-api/client/client.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/src/vpp-api/client/client.c b/src/vpp-api/client/client.c
index 68269bb9b55..a57db289250 100644
--- a/src/vpp-api/client/client.c
+++ b/src/vpp-api/client/client.c
@@ -33,6 +33,9 @@
#include "vppapiclient.h"
+bool timeout_cancelled;
+bool timeout_in_progress;
+
/*
* Asynchronous mode:
* Client registers a callback. All messages are sent to the callback.
@@ -234,27 +237,31 @@ vac_timeout_thread_fn (void *arg)
api_main_t *am = &api_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);
}
@@ -353,13 +360,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 +377,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);
}
@@ -453,7 +463,7 @@ vac_read (char **p, int *l, u16 timeout)
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:
@@ -484,15 +494,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 ();
a> 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
/*
 * Copyright (c) 2018 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef included_vector_avx2_h
#define included_vector_avx2_h

#include <vppinfra/clib.h>
#include <x86intrin.h>

/* *INDENT-OFF* */
#define foreach_avx2_vec256i \
  _(i,8,32,epi8) _(i,16,16,epi16) _(i,32,8,epi32)  _(i,64,4,epi64)
#define foreach_avx2_vec256u \
  _(u,8,32,epi8) _(u,16,16,epi16) _(u,32,8,epi32)  _(u,64,4,epi64)
#define foreach_avx2_vec256f \
  _(f,32,8,ps) _(f,64,4,pd)

#define _mm256_set1_epi64 _mm256_set1_epi64x

/* splat, load_unaligned, store_unaligned, is_all_zero, is_equal,
   is_all_equal */
#define _(t, s, c, i) \
static_always_inline t##s##x##c						\
t##s##x##c##_splat (t##s x)						\
{ return (t##s##x##c) _mm256_set1_##i (x); }				\
\
static_always_inline t##s##x##c						\
t##s##x##c##_load_unaligned (void *p)					\
{ return (t##s##x##c) _mm256_loadu_si256 (p); }				\
\
static_always_inline void						\
t##s##x##c##_store_unaligned (t##s##x##c v, void *p)			\
{ _mm256_storeu_si256 ((__m256i *) p, (__m256i) v); }			\
\
static_always_inline int						\
t##s##x##c##_is_all_zero (t##s##x##c x)					\
{ return _mm256_testz_si256 ((__m256i) x, (__m256i) x); }		\
\
static_always_inline int						\
t##s##x##c##_is_equal (t##s##x##c a, t##s##x##c b)			\
{ return t##s##x##c##_is_all_zero (a ^ b); }				\
\
static_always_inline int						\
t##s##x##c##_is_all_equal (t##s##x##c v, t##s x)			\
{ return t##s##x##c##_is_equal (v, t##s##x##c##_splat (x)); }		\
\
static_always_inline t##s##x##c                                         \
t##s##x##c##_interleave_lo (t##s##x##c a, t##s##x##c b)                 \
{ return (t##s##x##c) _mm256_unpacklo_##i ((__m256i) a, (__m256i) b); } \
\
static_always_inline t##s##x##c                                         \
t##s##x##c##_interleave_hi (t##s##x##c a, t##s##x##c b)                 \
{ return (t##s##x##c) _mm256_unpackhi_##i ((__m256i) a, (__m256i) b); } \


foreach_avx2_vec256i foreach_avx2_vec256u
#undef _
/* *INDENT-ON* */

always_inline u32x8
u32x8_permute (u32x8 v, u32x8 idx)
{
  return (u32x8) _mm256_permutevar8x32_epi32 ((__m256i) v, (__m256i) idx);
}

/* _extract_lo, _extract_hi */
/* *INDENT-OFF* */
#define _(t1,t2) \
always_inline t1							\
t2##_extract_lo (t2 v)							\
{ return (t1) _mm256_extracti128_si256 ((__m256i) v, 0); }		\
\
always_inline t1							\
t2##_extract_hi (t2 v)							\
{ return (t1) _mm256_extracti128_si256 ((__m256i) v, 1); }		\
\
always_inline t2							\
t2##_insert_lo (t2 v1, t1 v2)						\
{ return (t2) _mm256_inserti128_si256 ((__m256i) v1, (__m128i) v2, 0); }\
\
always_inline t2							\
t2##_insert_hi (t2 v1, t1 v2)						\
{ return (t2) _mm256_inserti128_si256 ((__m256i) v1, (__m128i) v2, 1); }\

_(u8x16, u8x32)
_(u16x8, u16x16)
_(u32x4, u32x8)
_(u64x2, u64x4)
#undef _
/* *INDENT-ON* */




static_always_inline u32
u8x32_msb_mask (u8x32 v)
{
  return _mm256_movemask_epi8 ((__m256i) v);
}

/* _extend_to_ */
/* *INDENT-OFF* */
#define _(f,t,i) \
static_always_inline t							\
f##_extend_to_##t (f x)							\
{ return (t) _mm256_cvt##i ((__m128i) x); }

_(u16x8, u32x8, epu16_epi32)
_(u16x8, u64x4, epu16_epi64)
_(u32x4, u64x4, epu32_epi64)
_(u8x16, u16x16, epu8_epi64)
_(u8x16, u32x8, epu8_epi32)
_(u8x16, u64x4, epu8_epi64)
_(i16x8, i32x8, epi16_epi32)
_(i16x8, i64x4, epi16_epi64)
_(i32x4, i64x4, epi32_epi64)
_(i8x16, i16x16, epi8_epi64)
_(i8x16, i32x8, epi8_epi32)
_(i8x16, i64x4, epi8_epi64)
#undef _
/* *INDENT-ON* */

static_always_inline u32x8
u32x8_byte_swap (u32x8 v)
{
  u8x32 swap = {
    3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12,
    3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
  };
  return (u32x8) _mm256_shuffle_epi8 ((__m256i) v, (__m256i) swap);
}

static_always_inline u16x16
u16x16_byte_swap (u16x16 v)
{
  u8x32 swap = {
    1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14,
    1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14
  };
  return (u16x16) _mm256_shuffle_epi8 ((__m256i) v, (__m256i) swap);
}

static_always_inline u32x8
u32x8_hadd (u32x8 v1, u32x8 v2)
{
  return (u32x8) _mm256_hadd_epi32 ((__m256i) v1, (__m256i) v2);
}

static_always_inline u16x16
u16x16_mask_last (u16x16 v, u8 n_last)
{
  const u16x16 masks[17] = {
    {0},
    {-1},
    {-1, -1},
    {-1, -1, -1},
    {-1, -1, -1, -1},
    {-1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
    {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  };

  ASSERT (n_last < 17);

  return v & masks[16 - n_last];
}

static_always_inline f32x8
f32x8_from_u32x8 (u32x8 v)
{
  return (f32x8) _mm256_cvtepi32_ps ((__m256i) v);
}

static_always_inline u32x8
u32x8_from_f32x8 (f32x8 v)
{
  return (u32x8) _mm256_cvttps_epi32 ((__m256) v);
}

#define u32x8_blend(a,b,m) \
  (u32x8) _mm256_blend_epi32 ((__m256i) a, (__m256i) b, m)

#define u16x16_blend(v1, v2, mask) \
  (u16x16) _mm256_blend_epi16 ((__m256i) (v1), (__m256i) (v2), mask)

static_always_inline u64x4
u64x4_gather (void *p0, void *p1, void *p2, void *p3)
{
  u64x4 r = {
    *(u64 *) p0, *(u64 *) p1, *(u64 *) p2, *(u64 *) p3
  };
  return r;
}

static_always_inline u32x8
u32x8_gather (void *p0, void *p1, void *p2, void *p3, void *p4, void *p5,
	      void *p6, void *p7)
{
  u32x8 r = {
    *(u32 *) p0, *(u32 *) p1, *(u32 *) p2, *(u32 *) p3,
    *(u32 *) p4, *(u32 *) p5, *(u32 *) p6, *(u32 *) p7,
  };
  return r;
}


static_always_inline void
u64x4_scatter (u64x4 r, void *p0, void *p1, void *p2, void *p3)
{
  *(u64 *) p0 = r[0];
  *(u64 *) p1 = r[1];
  *(u64 *) p2 = r[2];
  *(u64 *) p3 = r[3];
}

static_always_inline void
u32x8_scatter (u32x8 r, void *p0, void *p1, void *p2, void *p3, void *p4,
	       void *p5, void *p6, void *p7)
{
  *(u32 *) p0 = r[0];
  *(u32 *) p1 = r[1];
  *(u32 *) p2 = r[2];
  *(u32 *) p3 = r[3];
  *(u32 *) p4 = r[4];
  *(u32 *) p5 = r[5];
  *(u32 *) p6 = r[6];
  *(u32 *) p7 = r[7];
}

static_always_inline void
u64x4_scatter_one (u64x4 r, int index, void *p)
{
  *(u64 *) p = r[index];
}

static_always_inline void
u32x8_scatter_one (u32x8 r, int index, void *p)
{
  *(u32 *) p = r[index];
}

static_always_inline u8x32
u8x32_is_greater (u8x32 v1, u8x32 v2)
{
  return (u8x32) _mm256_cmpgt_epi8 ((__m256i) v1, (__m256i) v2);
}

static_always_inline u8x32
u8x32_blend (u8x32 v1, u8x32 v2, u8x32 mask)
{
  return (u8x32) _mm256_blendv_epi8 ((__m256i) v1, (__m256i) v2,
				     (__m256i) mask);
}

#define u32x8_permute_lanes(a, b, m) \
  (u32x8) _mm256_permute2x128_si256 ((__m256i) a, (__m256i) b, m)
#define u64x4_permute_lanes(a, b, m) \
  (u64x4) _mm256_permute2x128_si256 ((__m256i) a, (__m256i) b, m)

static_always_inline u32x8
u32x8_min (u32x8 a, u32x8 b)
{
  return (u32x8) _mm256_min_epu32 ((__m256i) a, (__m256i) b);
}

static_always_inline u32
u32x8_min_scalar (u32x8 v)
{
  return u32x4_min_scalar (u32x4_min (u32x8_extract_lo (v),
				      u32x8_extract_hi (v)));
}

static_always_inline void
u32x8_transpose (u32x8 a[8])
{
  u64x4 r[8], x, y;

  r[0] = (u64x4) u32x8_interleave_lo (a[0], a[1]);
  r[1] = (u64x4) u32x8_interleave_hi (a[0], a[1]);
  r[2] = (u64x4) u32x8_interleave_lo (a[2], a[3]);
  r[3] = (u64x4) u32x8_interleave_hi (a[2], a[3]);
  r[4] = (u64x4) u32x8_interleave_lo (a[4], a[5]);
  r[5] = (u64x4) u32x8_interleave_hi (a[4], a[5]);
  r[6] = (u64x4) u32x8_interleave_lo (a[6], a[7]);
  r[7] = (u64x4) u32x8_interleave_hi (a[6], a[7]);

  x = u64x4_interleave_lo (r[0], r[2]);
  y = u64x4_interleave_lo (r[4], r[6]);
  a[0] = u32x8_permute_lanes (x, y, 0x20);
  a[4] = u32x8_permute_lanes (x, y, 0x31);

  x = u64x4_interleave_hi (r[0], r[2]);
  y = u64x4_interleave_hi (r[4], r[6]);
  a[1] = u32x8_permute_lanes (x, y, 0x20);
  a[5] = u32x8_permute_lanes (x, y, 0x31);

  x = u64x4_interleave_lo (r[1], r[3]);
  y = u64x4_interleave_lo (r[5], r[7]);
  a[2] = u32x8_permute_lanes (x, y, 0x20);
  a[6] = u32x8_permute_lanes (x, y, 0x31);

  x = u64x4_interleave_hi (r[1], r[3]);
  y = u64x4_interleave_hi (r[5], r[7]);
  a[3] = u32x8_permute_lanes (x, y, 0x20);
  a[7] = u32x8_permute_lanes (x, y, 0x31);
}

static_always_inline void
u64x4_transpose (u64x4 a[8])
{
  u64x4 r[4];

  r[0] = u64x4_interleave_lo (a[0], a[1]);
  r[1] = u64x4_interleave_hi (a[0], a[1]);
  r[2] = u64x4_interleave_lo (a[2], a[3]);
  r[3] = u64x4_interleave_hi (a[2], a[3]);

  a[0] = u64x4_permute_lanes (r[0], r[2], 0x20);
  a[1] = u64x4_permute_lanes (r[1], r[3], 0x20);
  a[2] = u64x4_permute_lanes (r[0], r[2], 0x31);
  a[3] = u64x4_permute_lanes (r[1], r[3], 0x31);
}

#endif /* included_vector_avx2_h */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */