blob: 864d97e3de42ebcf235e0dfee11c8ac7b631d5c6 [file] [log] [blame]
Dave Barach371e4e12016-07-08 09:38:52 -04001/*
Ed Warnickecb9cada2015-12-08 15:45:58 -07002 *------------------------------------------------------------------
Florin Corase86a8ed2018-01-05 03:20:25 -08003 * svm_queue.c - unidirectional shared-memory queues
Ed Warnickecb9cada2015-12-08 15:45:58 -07004 *
Florin Corasc5df8c72019-04-08 07:42:30 -07005 * Copyright (c) 2009-2019 Cisco and/or its affiliates.
Ed Warnickecb9cada2015-12-08 15:45:58 -07006 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
Florin Corase86a8ed2018-01-05 03:20:25 -080020
Ed Warnickecb9cada2015-12-08 15:45:58 -070021#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <pthread.h>
25#include <vppinfra/mem.h>
26#include <vppinfra/format.h>
27#include <vppinfra/cache.h>
Florin Corase86a8ed2018-01-05 03:20:25 -080028#include <svm/queue.h>
Mohsin Kazmi3fca5672018-01-04 18:57:26 +010029#include <vppinfra/time.h>
Florin Coras99368312018-08-02 10:45:44 -070030#include <vppinfra/lock.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070031
Florin Corase86a8ed2018-01-05 03:20:25 -080032svm_queue_t *
Florin Corasc470e222018-08-01 07:53:18 -070033svm_queue_init (void *base, int nels, int elsize)
Ed Warnickecb9cada2015-12-08 15:45:58 -070034{
Florin Corase86a8ed2018-01-05 03:20:25 -080035 svm_queue_t *q;
Dave Barach371e4e12016-07-08 09:38:52 -040036 pthread_mutexattr_t attr;
37 pthread_condattr_t cattr;
Ed Warnickecb9cada2015-12-08 15:45:58 -070038
Florin Corasc470e222018-08-01 07:53:18 -070039 q = (svm_queue_t *) base;
Dave Barachb7b92992018-10-17 10:38:51 -040040 clib_memset (q, 0, sizeof (*q));
Ed Warnickecb9cada2015-12-08 15:45:58 -070041
Dave Barach371e4e12016-07-08 09:38:52 -040042 q->elsize = elsize;
43 q->maxsize = nels;
Florin Corasc470e222018-08-01 07:53:18 -070044 q->producer_evtfd = -1;
45 q->consumer_evtfd = -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -070046
Dave Barachb7b92992018-10-17 10:38:51 -040047 clib_memset (&attr, 0, sizeof (attr));
48 clib_memset (&cattr, 0, sizeof (cattr));
Ed Warnickecb9cada2015-12-08 15:45:58 -070049
Dave Barach371e4e12016-07-08 09:38:52 -040050 if (pthread_mutexattr_init (&attr))
51 clib_unix_warning ("mutexattr_init");
52 if (pthread_mutexattr_setpshared (&attr, PTHREAD_PROCESS_SHARED))
53 clib_unix_warning ("pthread_mutexattr_setpshared");
Florin Coras2440a8a2020-11-27 09:49:10 -080054 if (pthread_mutexattr_setrobust (&attr, PTHREAD_MUTEX_ROBUST))
55 clib_unix_warning ("setrobust");
Dave Barach371e4e12016-07-08 09:38:52 -040056 if (pthread_mutex_init (&q->mutex, &attr))
57 clib_unix_warning ("mutex_init");
58 if (pthread_mutexattr_destroy (&attr))
59 clib_unix_warning ("mutexattr_destroy");
60 if (pthread_condattr_init (&cattr))
61 clib_unix_warning ("condattr_init");
62 /* prints funny-looking messages in the Linux target */
63 if (pthread_condattr_setpshared (&cattr, PTHREAD_PROCESS_SHARED))
64 clib_unix_warning ("condattr_setpshared");
65 if (pthread_cond_init (&q->condvar, &cattr))
66 clib_unix_warning ("cond_init1");
67 if (pthread_condattr_destroy (&cattr))
68 clib_unix_warning ("cond_init2");
69
70 return (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -070071}
72
Florin Corasc470e222018-08-01 07:53:18 -070073svm_queue_t *
74svm_queue_alloc_and_init (int nels, int elsize, int consumer_pid)
75{
76 svm_queue_t *q;
77
78 q = clib_mem_alloc_aligned (sizeof (svm_queue_t)
79 + nels * elsize, CLIB_CACHE_LINE_BYTES);
Dave Barachb7b92992018-10-17 10:38:51 -040080 clib_memset (q, 0, sizeof (*q));
Florin Corasc470e222018-08-01 07:53:18 -070081 q = svm_queue_init (q, nels, elsize);
82 q->consumer_pid = consumer_pid;
83
84 return q;
85}
86
Ed Warnickecb9cada2015-12-08 15:45:58 -070087/*
Florin Corase86a8ed2018-01-05 03:20:25 -080088 * svm_queue_free
Ed Warnickecb9cada2015-12-08 15:45:58 -070089 */
Dave Barach371e4e12016-07-08 09:38:52 -040090void
Florin Corase86a8ed2018-01-05 03:20:25 -080091svm_queue_free (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -070092{
Dave Barach371e4e12016-07-08 09:38:52 -040093 (void) pthread_mutex_destroy (&q->mutex);
94 (void) pthread_cond_destroy (&q->condvar);
95 clib_mem_free (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -070096}
97
Dave Barach371e4e12016-07-08 09:38:52 -040098void
Florin Corase86a8ed2018-01-05 03:20:25 -080099svm_queue_lock (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700100{
Florin Coras2440a8a2020-11-27 09:49:10 -0800101 int rv = pthread_mutex_lock (&q->mutex);
102 if (PREDICT_FALSE (rv == EOWNERDEAD))
103 pthread_mutex_consistent (&q->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700104}
105
Florin Coras1d56ac42020-12-02 07:57:00 -0800106static int
107svm_queue_trylock (svm_queue_t * q)
108{
109 int rv = pthread_mutex_trylock (&q->mutex);
110 if (PREDICT_FALSE (rv == EOWNERDEAD))
111 rv = pthread_mutex_consistent (&q->mutex);
112 return rv;
113}
114
Dave Barach371e4e12016-07-08 09:38:52 -0400115void
Florin Corase86a8ed2018-01-05 03:20:25 -0800116svm_queue_unlock (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700117{
Dave Barach371e4e12016-07-08 09:38:52 -0400118 pthread_mutex_unlock (&q->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700119}
120
Dave Barach371e4e12016-07-08 09:38:52 -0400121int
Florin Corase86a8ed2018-01-05 03:20:25 -0800122svm_queue_is_full (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700123{
Dave Barach371e4e12016-07-08 09:38:52 -0400124 return q->cursize == q->maxsize;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700125}
126
Florin Corasc470e222018-08-01 07:53:18 -0700127static inline void
Florin Corasfea813a2019-12-27 10:26:56 -0800128svm_queue_send_signal_inline (svm_queue_t * q, u8 is_prod)
Florin Corasc470e222018-08-01 07:53:18 -0700129{
130 if (q->producer_evtfd == -1)
131 {
132 (void) pthread_cond_broadcast (&q->condvar);
133 }
134 else
135 {
136 int __clib_unused rv, fd;
137 u64 data = 1;
Florin Coras14598772018-09-04 19:47:52 -0700138 ASSERT (q->consumer_evtfd > 0 && q->producer_evtfd > 0);
Florin Corasc470e222018-08-01 07:53:18 -0700139 fd = is_prod ? q->producer_evtfd : q->consumer_evtfd;
140 rv = write (fd, &data, sizeof (data));
Florin Corase4a08c12020-01-08 02:37:57 +0000141 if (PREDICT_FALSE (rv < 0))
142 clib_unix_warning ("signal write on %d returned %d", fd, rv);
Florin Corasc470e222018-08-01 07:53:18 -0700143 }
144}
145
Florin Corasfea813a2019-12-27 10:26:56 -0800146void
147svm_queue_send_signal (svm_queue_t * q, u8 is_prod)
148{
149 svm_queue_send_signal_inline (q, is_prod);
150}
151
Florin Coras99368312018-08-02 10:45:44 -0700152static inline void
153svm_queue_wait_inline (svm_queue_t * q)
154{
155 if (q->producer_evtfd == -1)
156 {
157 pthread_cond_wait (&q->condvar, &q->mutex);
158 }
159 else
160 {
161 /* Fake a wait for event. We could use epoll but that would mean
162 * using yet another fd. Should do for now */
163 u32 cursize = q->cursize;
Ping Yua4748942019-03-12 05:28:16 -0400164 svm_queue_unlock (q);
Florin Coras99368312018-08-02 10:45:44 -0700165 while (q->cursize == cursize)
166 CLIB_PAUSE ();
Ping Yua4748942019-03-12 05:28:16 -0400167 svm_queue_lock (q);
Florin Coras99368312018-08-02 10:45:44 -0700168 }
169}
170
171void
172svm_queue_wait (svm_queue_t * q)
173{
174 svm_queue_wait_inline (q);
175}
176
177static inline int
178svm_queue_timedwait_inline (svm_queue_t * q, double timeout)
179{
180 struct timespec ts;
181 ts.tv_sec = unix_time_now () + (u32) timeout;
182 ts.tv_nsec = (timeout - (u32) timeout) * 1e9;
183
184 if (q->producer_evtfd == -1)
185 {
186 return pthread_cond_timedwait (&q->condvar, &q->mutex, &ts);
187 }
188 else
189 {
190 double max_time = unix_time_now () + timeout;
191 u32 cursize = q->cursize;
192 int rv;
193
Ping Yua4748942019-03-12 05:28:16 -0400194 svm_queue_unlock (q);
Florin Coras99368312018-08-02 10:45:44 -0700195 while (q->cursize == cursize && unix_time_now () < max_time)
196 CLIB_PAUSE ();
197 rv = unix_time_now () < max_time ? 0 : ETIMEDOUT;
Vratko Polaka29d18a2019-05-21 13:47:29 +0200198 svm_queue_lock (q);
Florin Coras99368312018-08-02 10:45:44 -0700199 return rv;
200 }
201}
202
203int
204svm_queue_timedwait (svm_queue_t * q, double timeout)
205{
206 return svm_queue_timedwait_inline (q, timeout);
207}
208
Ed Warnickecb9cada2015-12-08 15:45:58 -0700209/*
Florin Corase86a8ed2018-01-05 03:20:25 -0800210 * svm_queue_add_nolock
Ed Warnickecb9cada2015-12-08 15:45:58 -0700211 */
Dave Barach371e4e12016-07-08 09:38:52 -0400212int
Florin Corase86a8ed2018-01-05 03:20:25 -0800213svm_queue_add_nolock (svm_queue_t * q, u8 * elem)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700214{
Dave Barach371e4e12016-07-08 09:38:52 -0400215 i8 *tailp;
216 int need_broadcast = 0;
217
218 if (PREDICT_FALSE (q->cursize == q->maxsize))
219 {
220 while (q->cursize == q->maxsize)
Florin Coras99368312018-08-02 10:45:44 -0700221 svm_queue_wait_inline (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700222 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223
Dave Barach371e4e12016-07-08 09:38:52 -0400224 tailp = (i8 *) (&q->data[0] + q->elsize * q->tail);
Dave Barach178cf492018-11-13 16:34:13 -0500225 clib_memcpy_fast (tailp, elem, q->elsize);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700226
Dave Barach371e4e12016-07-08 09:38:52 -0400227 q->tail++;
228 q->cursize++;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229
Dave Barach371e4e12016-07-08 09:38:52 -0400230 need_broadcast = (q->cursize == 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700231
Dave Barach371e4e12016-07-08 09:38:52 -0400232 if (q->tail == q->maxsize)
233 q->tail = 0;
234
235 if (need_broadcast)
Florin Corasfea813a2019-12-27 10:26:56 -0800236 svm_queue_send_signal_inline (q, 1);
Dave Barach371e4e12016-07-08 09:38:52 -0400237 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700238}
239
Florin Coras3c2fed52018-07-04 04:15:05 -0700240void
Florin Corase86a8ed2018-01-05 03:20:25 -0800241svm_queue_add_raw (svm_queue_t * q, u8 * elem)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700242{
Dave Barach371e4e12016-07-08 09:38:52 -0400243 i8 *tailp;
244
Dave Barach371e4e12016-07-08 09:38:52 -0400245 tailp = (i8 *) (&q->data[0] + q->elsize * q->tail);
Dave Barach178cf492018-11-13 16:34:13 -0500246 clib_memcpy_fast (tailp, elem, q->elsize);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700247
Florin Coras3c2fed52018-07-04 04:15:05 -0700248 q->tail = (q->tail + 1) % q->maxsize;
Dave Barach371e4e12016-07-08 09:38:52 -0400249 q->cursize++;
Florin Coras99368312018-08-02 10:45:44 -0700250
251 if (q->cursize == 1)
Florin Corasfea813a2019-12-27 10:26:56 -0800252 svm_queue_send_signal_inline (q, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700253}
254
255
256/*
Florin Corase86a8ed2018-01-05 03:20:25 -0800257 * svm_queue_add
Ed Warnickecb9cada2015-12-08 15:45:58 -0700258 */
Dave Barach371e4e12016-07-08 09:38:52 -0400259int
Florin Corase86a8ed2018-01-05 03:20:25 -0800260svm_queue_add (svm_queue_t * q, u8 * elem, int nowait)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700261{
Dave Barach371e4e12016-07-08 09:38:52 -0400262 i8 *tailp;
263 int need_broadcast = 0;
264
265 if (nowait)
266 {
267 /* zero on success */
Florin Coras1d56ac42020-12-02 07:57:00 -0800268 if (svm_queue_trylock (q))
Dave Barach371e4e12016-07-08 09:38:52 -0400269 {
270 return (-1);
271 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700272 }
Dave Barach371e4e12016-07-08 09:38:52 -0400273 else
Ping Yua4748942019-03-12 05:28:16 -0400274 svm_queue_lock (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700275
Dave Barach371e4e12016-07-08 09:38:52 -0400276 if (PREDICT_FALSE (q->cursize == q->maxsize))
277 {
278 if (nowait)
279 {
Ping Yua4748942019-03-12 05:28:16 -0400280 svm_queue_unlock (q);
Dave Barach371e4e12016-07-08 09:38:52 -0400281 return (-2);
282 }
283 while (q->cursize == q->maxsize)
Florin Coras99368312018-08-02 10:45:44 -0700284 svm_queue_wait_inline (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700286
Dave Barach371e4e12016-07-08 09:38:52 -0400287 tailp = (i8 *) (&q->data[0] + q->elsize * q->tail);
Dave Barach178cf492018-11-13 16:34:13 -0500288 clib_memcpy_fast (tailp, elem, q->elsize);
Dave Barach371e4e12016-07-08 09:38:52 -0400289
290 q->tail++;
291 q->cursize++;
292
293 need_broadcast = (q->cursize == 1);
294
295 if (q->tail == q->maxsize)
296 q->tail = 0;
297
298 if (need_broadcast)
Florin Corasfea813a2019-12-27 10:26:56 -0800299 svm_queue_send_signal_inline (q, 1);
Florin Corasc470e222018-08-01 07:53:18 -0700300
Ping Yua4748942019-03-12 05:28:16 -0400301 svm_queue_unlock (q);
Dave Barach371e4e12016-07-08 09:38:52 -0400302
303 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700304}
305
306/*
Florin Corase86a8ed2018-01-05 03:20:25 -0800307 * svm_queue_add2
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200308 */
309int
Florin Corase86a8ed2018-01-05 03:20:25 -0800310svm_queue_add2 (svm_queue_t * q, u8 * elem, u8 * elem2, int nowait)
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200311{
312 i8 *tailp;
313 int need_broadcast = 0;
314
315 if (nowait)
316 {
317 /* zero on success */
Florin Coras1d56ac42020-12-02 07:57:00 -0800318 if (svm_queue_trylock (q))
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200319 {
320 return (-1);
321 }
322 }
323 else
Ping Yua4748942019-03-12 05:28:16 -0400324 svm_queue_lock (q);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200325
326 if (PREDICT_FALSE (q->cursize + 1 == q->maxsize))
327 {
328 if (nowait)
329 {
Ping Yua4748942019-03-12 05:28:16 -0400330 svm_queue_unlock (q);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200331 return (-2);
332 }
333 while (q->cursize + 1 == q->maxsize)
Florin Coras99368312018-08-02 10:45:44 -0700334 svm_queue_wait_inline (q);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200335 }
336
337 tailp = (i8 *) (&q->data[0] + q->elsize * q->tail);
Dave Barach178cf492018-11-13 16:34:13 -0500338 clib_memcpy_fast (tailp, elem, q->elsize);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200339
340 q->tail++;
341 q->cursize++;
342
343 if (q->tail == q->maxsize)
344 q->tail = 0;
345
346 need_broadcast = (q->cursize == 1);
347
348 tailp = (i8 *) (&q->data[0] + q->elsize * q->tail);
Dave Barach178cf492018-11-13 16:34:13 -0500349 clib_memcpy_fast (tailp, elem2, q->elsize);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200350
351 q->tail++;
352 q->cursize++;
353
354 if (q->tail == q->maxsize)
355 q->tail = 0;
356
357 if (need_broadcast)
Florin Corasfea813a2019-12-27 10:26:56 -0800358 svm_queue_send_signal_inline (q, 1);
Florin Corasc470e222018-08-01 07:53:18 -0700359
Ping Yua4748942019-03-12 05:28:16 -0400360 svm_queue_unlock (q);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200361
362 return 0;
363}
364
365/*
Florin Corase86a8ed2018-01-05 03:20:25 -0800366 * svm_queue_sub
Ed Warnickecb9cada2015-12-08 15:45:58 -0700367 */
Dave Barach371e4e12016-07-08 09:38:52 -0400368int
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100369svm_queue_sub (svm_queue_t * q, u8 * elem, svm_q_conditional_wait_t cond,
370 u32 time)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700371{
Dave Barach371e4e12016-07-08 09:38:52 -0400372 i8 *headp;
373 int need_broadcast = 0;
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100374 int rc = 0;
Dave Barach371e4e12016-07-08 09:38:52 -0400375
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100376 if (cond == SVM_Q_NOWAIT)
Dave Barach371e4e12016-07-08 09:38:52 -0400377 {
378 /* zero on success */
Florin Coras1d56ac42020-12-02 07:57:00 -0800379 if (svm_queue_trylock (q))
Dave Barach371e4e12016-07-08 09:38:52 -0400380 {
381 return (-1);
382 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700383 }
Dave Barach371e4e12016-07-08 09:38:52 -0400384 else
Ping Yua4748942019-03-12 05:28:16 -0400385 svm_queue_lock (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700386
Dave Barach371e4e12016-07-08 09:38:52 -0400387 if (PREDICT_FALSE (q->cursize == 0))
388 {
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100389 if (cond == SVM_Q_NOWAIT)
Dave Barach371e4e12016-07-08 09:38:52 -0400390 {
Ping Yua4748942019-03-12 05:28:16 -0400391 svm_queue_unlock (q);
Dave Barach371e4e12016-07-08 09:38:52 -0400392 return (-2);
393 }
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100394 else if (cond == SVM_Q_TIMEDWAIT)
Dave Barach371e4e12016-07-08 09:38:52 -0400395 {
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100396 while (q->cursize == 0 && rc == 0)
Florin Coras99368312018-08-02 10:45:44 -0700397 rc = svm_queue_timedwait_inline (q, time);
398
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100399 if (rc == ETIMEDOUT)
400 {
Ping Yua4748942019-03-12 05:28:16 -0400401 svm_queue_unlock (q);
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100402 return ETIMEDOUT;
403 }
404 }
405 else
406 {
407 while (q->cursize == 0)
Florin Coras99368312018-08-02 10:45:44 -0700408 svm_queue_wait_inline (q);
Dave Barach371e4e12016-07-08 09:38:52 -0400409 }
410 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700411
Dave Barach371e4e12016-07-08 09:38:52 -0400412 headp = (i8 *) (&q->data[0] + q->elsize * q->head);
Dave Barach178cf492018-11-13 16:34:13 -0500413 clib_memcpy_fast (elem, headp, q->elsize);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414
Dave Barach371e4e12016-07-08 09:38:52 -0400415 q->head++;
Dave Barach68b0fb02017-02-28 15:15:56 -0500416 /* $$$$ JFC shouldn't this be == 0? */
Dave Barach371e4e12016-07-08 09:38:52 -0400417 if (q->cursize == q->maxsize)
418 need_broadcast = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700419
Dave Barach371e4e12016-07-08 09:38:52 -0400420 q->cursize--;
421
422 if (q->head == q->maxsize)
423 q->head = 0;
424
425 if (need_broadcast)
Florin Corasfea813a2019-12-27 10:26:56 -0800426 svm_queue_send_signal_inline (q, 0);
Dave Barach371e4e12016-07-08 09:38:52 -0400427
Ping Yua4748942019-03-12 05:28:16 -0400428 svm_queue_unlock (q);
Dave Barach371e4e12016-07-08 09:38:52 -0400429
430 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700431}
432
Dave Barach371e4e12016-07-08 09:38:52 -0400433int
Florin Corase86a8ed2018-01-05 03:20:25 -0800434svm_queue_sub2 (svm_queue_t * q, u8 * elem)
435{
436 int need_broadcast;
437 i8 *headp;
438
Ping Yua4748942019-03-12 05:28:16 -0400439 svm_queue_lock (q);
Florin Corase86a8ed2018-01-05 03:20:25 -0800440 if (q->cursize == 0)
441 {
Ping Yua4748942019-03-12 05:28:16 -0400442 svm_queue_unlock (q);
Florin Corase86a8ed2018-01-05 03:20:25 -0800443 return -1;
444 }
445
446 headp = (i8 *) (&q->data[0] + q->elsize * q->head);
Dave Barach178cf492018-11-13 16:34:13 -0500447 clib_memcpy_fast (elem, headp, q->elsize);
Florin Corase86a8ed2018-01-05 03:20:25 -0800448
449 q->head++;
450 need_broadcast = (q->cursize == q->maxsize / 2);
451 q->cursize--;
452
453 if (PREDICT_FALSE (q->head == q->maxsize))
454 q->head = 0;
Ping Yua4748942019-03-12 05:28:16 -0400455 svm_queue_unlock (q);
Florin Corase86a8ed2018-01-05 03:20:25 -0800456
457 if (need_broadcast)
Florin Corasfea813a2019-12-27 10:26:56 -0800458 svm_queue_send_signal_inline (q, 0);
Florin Corase86a8ed2018-01-05 03:20:25 -0800459
460 return 0;
461}
462
463int
464svm_queue_sub_raw (svm_queue_t * q, u8 * elem)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700465{
Florin Corasfea813a2019-12-27 10:26:56 -0800466 int need_broadcast;
Dave Barach371e4e12016-07-08 09:38:52 -0400467 i8 *headp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700468
Dave Barach371e4e12016-07-08 09:38:52 -0400469 if (PREDICT_FALSE (q->cursize == 0))
470 {
471 while (q->cursize == 0)
472 ;
473 }
474
475 headp = (i8 *) (&q->data[0] + q->elsize * q->head);
Dave Barach178cf492018-11-13 16:34:13 -0500476 clib_memcpy_fast (elem, headp, q->elsize);
Dave Barach371e4e12016-07-08 09:38:52 -0400477
Florin Corasfea813a2019-12-27 10:26:56 -0800478 need_broadcast = q->cursize == q->maxsize;
479
Florin Coras3c2fed52018-07-04 04:15:05 -0700480 q->head = (q->head + 1) % q->maxsize;
Dave Barach371e4e12016-07-08 09:38:52 -0400481 q->cursize--;
482
Florin Corasfea813a2019-12-27 10:26:56 -0800483 if (PREDICT_FALSE (need_broadcast))
484 svm_queue_send_signal_inline (q, 0);
485
Dave Barach371e4e12016-07-08 09:38:52 -0400486 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700487}
Dave Barach371e4e12016-07-08 09:38:52 -0400488
Florin Corasc470e222018-08-01 07:53:18 -0700489void
490svm_queue_set_producer_event_fd (svm_queue_t * q, int fd)
491{
492 q->producer_evtfd = fd;
493}
494
495void
496svm_queue_set_consumer_event_fd (svm_queue_t * q, int fd)
497{
498 q->consumer_evtfd = fd;
499}
500
Dave Barach371e4e12016-07-08 09:38:52 -0400501/*
502 * fd.io coding-style-patch-verification: ON
503 *
504 * Local Variables:
505 * eval: (c-set-style "gnu")
506 * End:
507 */