blob: 4d37a5f7810c0032ac09419ea90a95097e51fd98 [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");
54 if (pthread_mutex_init (&q->mutex, &attr))
55 clib_unix_warning ("mutex_init");
56 if (pthread_mutexattr_destroy (&attr))
57 clib_unix_warning ("mutexattr_destroy");
58 if (pthread_condattr_init (&cattr))
59 clib_unix_warning ("condattr_init");
60 /* prints funny-looking messages in the Linux target */
61 if (pthread_condattr_setpshared (&cattr, PTHREAD_PROCESS_SHARED))
62 clib_unix_warning ("condattr_setpshared");
63 if (pthread_cond_init (&q->condvar, &cattr))
64 clib_unix_warning ("cond_init1");
65 if (pthread_condattr_destroy (&cattr))
66 clib_unix_warning ("cond_init2");
67
68 return (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -070069}
70
Florin Corasc470e222018-08-01 07:53:18 -070071svm_queue_t *
72svm_queue_alloc_and_init (int nels, int elsize, int consumer_pid)
73{
74 svm_queue_t *q;
75
76 q = clib_mem_alloc_aligned (sizeof (svm_queue_t)
77 + nels * elsize, CLIB_CACHE_LINE_BYTES);
Dave Barachb7b92992018-10-17 10:38:51 -040078 clib_memset (q, 0, sizeof (*q));
Florin Corasc470e222018-08-01 07:53:18 -070079 q = svm_queue_init (q, nels, elsize);
80 q->consumer_pid = consumer_pid;
81
82 return q;
83}
84
Ed Warnickecb9cada2015-12-08 15:45:58 -070085/*
Florin Corase86a8ed2018-01-05 03:20:25 -080086 * svm_queue_free
Ed Warnickecb9cada2015-12-08 15:45:58 -070087 */
Dave Barach371e4e12016-07-08 09:38:52 -040088void
Florin Corase86a8ed2018-01-05 03:20:25 -080089svm_queue_free (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -070090{
Dave Barach371e4e12016-07-08 09:38:52 -040091 (void) pthread_mutex_destroy (&q->mutex);
92 (void) pthread_cond_destroy (&q->condvar);
93 clib_mem_free (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -070094}
95
Dave Barach371e4e12016-07-08 09:38:52 -040096void
Florin Corase86a8ed2018-01-05 03:20:25 -080097svm_queue_lock (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -070098{
Dave Barach371e4e12016-07-08 09:38:52 -040099 pthread_mutex_lock (&q->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700100}
101
Dave Barach371e4e12016-07-08 09:38:52 -0400102void
Florin Corase86a8ed2018-01-05 03:20:25 -0800103svm_queue_unlock (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700104{
Dave Barach371e4e12016-07-08 09:38:52 -0400105 pthread_mutex_unlock (&q->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700106}
107
Dave Barach371e4e12016-07-08 09:38:52 -0400108int
Florin Corase86a8ed2018-01-05 03:20:25 -0800109svm_queue_is_full (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700110{
Dave Barach371e4e12016-07-08 09:38:52 -0400111 return q->cursize == q->maxsize;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700112}
113
Florin Corasc470e222018-08-01 07:53:18 -0700114static inline void
Florin Corasfea813a2019-12-27 10:26:56 -0800115svm_queue_send_signal_inline (svm_queue_t * q, u8 is_prod)
Florin Corasc470e222018-08-01 07:53:18 -0700116{
117 if (q->producer_evtfd == -1)
118 {
119 (void) pthread_cond_broadcast (&q->condvar);
120 }
121 else
122 {
123 int __clib_unused rv, fd;
124 u64 data = 1;
Florin Coras14598772018-09-04 19:47:52 -0700125 ASSERT (q->consumer_evtfd > 0 && q->producer_evtfd > 0);
Florin Corasc470e222018-08-01 07:53:18 -0700126 fd = is_prod ? q->producer_evtfd : q->consumer_evtfd;
127 rv = write (fd, &data, sizeof (data));
Florin Corasfea813a2019-12-27 10:26:56 -0800128 if (PREDICT_FALSE (rv))
129 clib_unix_warning ("signal write returned %d", rv);
Florin Corasc470e222018-08-01 07:53:18 -0700130 }
131}
132
Florin Corasfea813a2019-12-27 10:26:56 -0800133void
134svm_queue_send_signal (svm_queue_t * q, u8 is_prod)
135{
136 svm_queue_send_signal_inline (q, is_prod);
137}
138
Florin Coras99368312018-08-02 10:45:44 -0700139static inline void
140svm_queue_wait_inline (svm_queue_t * q)
141{
142 if (q->producer_evtfd == -1)
143 {
144 pthread_cond_wait (&q->condvar, &q->mutex);
145 }
146 else
147 {
148 /* Fake a wait for event. We could use epoll but that would mean
149 * using yet another fd. Should do for now */
150 u32 cursize = q->cursize;
Ping Yua4748942019-03-12 05:28:16 -0400151 svm_queue_unlock (q);
Florin Coras99368312018-08-02 10:45:44 -0700152 while (q->cursize == cursize)
153 CLIB_PAUSE ();
Ping Yua4748942019-03-12 05:28:16 -0400154 svm_queue_lock (q);
Florin Coras99368312018-08-02 10:45:44 -0700155 }
156}
157
158void
159svm_queue_wait (svm_queue_t * q)
160{
161 svm_queue_wait_inline (q);
162}
163
164static inline int
165svm_queue_timedwait_inline (svm_queue_t * q, double timeout)
166{
167 struct timespec ts;
168 ts.tv_sec = unix_time_now () + (u32) timeout;
169 ts.tv_nsec = (timeout - (u32) timeout) * 1e9;
170
171 if (q->producer_evtfd == -1)
172 {
173 return pthread_cond_timedwait (&q->condvar, &q->mutex, &ts);
174 }
175 else
176 {
177 double max_time = unix_time_now () + timeout;
178 u32 cursize = q->cursize;
179 int rv;
180
Ping Yua4748942019-03-12 05:28:16 -0400181 svm_queue_unlock (q);
Florin Coras99368312018-08-02 10:45:44 -0700182 while (q->cursize == cursize && unix_time_now () < max_time)
183 CLIB_PAUSE ();
184 rv = unix_time_now () < max_time ? 0 : ETIMEDOUT;
Vratko Polaka29d18a2019-05-21 13:47:29 +0200185 svm_queue_lock (q);
Florin Coras99368312018-08-02 10:45:44 -0700186 return rv;
187 }
188}
189
190int
191svm_queue_timedwait (svm_queue_t * q, double timeout)
192{
193 return svm_queue_timedwait_inline (q, timeout);
194}
195
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196/*
Florin Corase86a8ed2018-01-05 03:20:25 -0800197 * svm_queue_add_nolock
Ed Warnickecb9cada2015-12-08 15:45:58 -0700198 */
Dave Barach371e4e12016-07-08 09:38:52 -0400199int
Florin Corase86a8ed2018-01-05 03:20:25 -0800200svm_queue_add_nolock (svm_queue_t * q, u8 * elem)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700201{
Dave Barach371e4e12016-07-08 09:38:52 -0400202 i8 *tailp;
203 int need_broadcast = 0;
204
205 if (PREDICT_FALSE (q->cursize == q->maxsize))
206 {
207 while (q->cursize == q->maxsize)
Florin Coras99368312018-08-02 10:45:44 -0700208 svm_queue_wait_inline (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700209 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210
Dave Barach371e4e12016-07-08 09:38:52 -0400211 tailp = (i8 *) (&q->data[0] + q->elsize * q->tail);
Dave Barach178cf492018-11-13 16:34:13 -0500212 clib_memcpy_fast (tailp, elem, q->elsize);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700213
Dave Barach371e4e12016-07-08 09:38:52 -0400214 q->tail++;
215 q->cursize++;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700216
Dave Barach371e4e12016-07-08 09:38:52 -0400217 need_broadcast = (q->cursize == 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700218
Dave Barach371e4e12016-07-08 09:38:52 -0400219 if (q->tail == q->maxsize)
220 q->tail = 0;
221
222 if (need_broadcast)
Florin Corasfea813a2019-12-27 10:26:56 -0800223 svm_queue_send_signal_inline (q, 1);
Dave Barach371e4e12016-07-08 09:38:52 -0400224 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700225}
226
Florin Coras3c2fed52018-07-04 04:15:05 -0700227void
Florin Corase86a8ed2018-01-05 03:20:25 -0800228svm_queue_add_raw (svm_queue_t * q, u8 * elem)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229{
Dave Barach371e4e12016-07-08 09:38:52 -0400230 i8 *tailp;
231
Dave Barach371e4e12016-07-08 09:38:52 -0400232 tailp = (i8 *) (&q->data[0] + q->elsize * q->tail);
Dave Barach178cf492018-11-13 16:34:13 -0500233 clib_memcpy_fast (tailp, elem, q->elsize);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700234
Florin Coras3c2fed52018-07-04 04:15:05 -0700235 q->tail = (q->tail + 1) % q->maxsize;
Dave Barach371e4e12016-07-08 09:38:52 -0400236 q->cursize++;
Florin Coras99368312018-08-02 10:45:44 -0700237
238 if (q->cursize == 1)
Florin Corasfea813a2019-12-27 10:26:56 -0800239 svm_queue_send_signal_inline (q, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700240}
241
242
243/*
Florin Corase86a8ed2018-01-05 03:20:25 -0800244 * svm_queue_add
Ed Warnickecb9cada2015-12-08 15:45:58 -0700245 */
Dave Barach371e4e12016-07-08 09:38:52 -0400246int
Florin Corase86a8ed2018-01-05 03:20:25 -0800247svm_queue_add (svm_queue_t * q, u8 * elem, int nowait)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700248{
Dave Barach371e4e12016-07-08 09:38:52 -0400249 i8 *tailp;
250 int need_broadcast = 0;
251
252 if (nowait)
253 {
254 /* zero on success */
255 if (pthread_mutex_trylock (&q->mutex))
256 {
257 return (-1);
258 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700259 }
Dave Barach371e4e12016-07-08 09:38:52 -0400260 else
Ping Yua4748942019-03-12 05:28:16 -0400261 svm_queue_lock (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700262
Dave Barach371e4e12016-07-08 09:38:52 -0400263 if (PREDICT_FALSE (q->cursize == q->maxsize))
264 {
265 if (nowait)
266 {
Ping Yua4748942019-03-12 05:28:16 -0400267 svm_queue_unlock (q);
Dave Barach371e4e12016-07-08 09:38:52 -0400268 return (-2);
269 }
270 while (q->cursize == q->maxsize)
Florin Coras99368312018-08-02 10:45:44 -0700271 svm_queue_wait_inline (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700272 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700273
Dave Barach371e4e12016-07-08 09:38:52 -0400274 tailp = (i8 *) (&q->data[0] + q->elsize * q->tail);
Dave Barach178cf492018-11-13 16:34:13 -0500275 clib_memcpy_fast (tailp, elem, q->elsize);
Dave Barach371e4e12016-07-08 09:38:52 -0400276
277 q->tail++;
278 q->cursize++;
279
280 need_broadcast = (q->cursize == 1);
281
282 if (q->tail == q->maxsize)
283 q->tail = 0;
284
285 if (need_broadcast)
Florin Corasfea813a2019-12-27 10:26:56 -0800286 svm_queue_send_signal_inline (q, 1);
Florin Corasc470e222018-08-01 07:53:18 -0700287
Ping Yua4748942019-03-12 05:28:16 -0400288 svm_queue_unlock (q);
Dave Barach371e4e12016-07-08 09:38:52 -0400289
290 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700291}
292
293/*
Florin Corase86a8ed2018-01-05 03:20:25 -0800294 * svm_queue_add2
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200295 */
296int
Florin Corase86a8ed2018-01-05 03:20:25 -0800297svm_queue_add2 (svm_queue_t * q, u8 * elem, u8 * elem2, int nowait)
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200298{
299 i8 *tailp;
300 int need_broadcast = 0;
301
302 if (nowait)
303 {
304 /* zero on success */
305 if (pthread_mutex_trylock (&q->mutex))
306 {
307 return (-1);
308 }
309 }
310 else
Ping Yua4748942019-03-12 05:28:16 -0400311 svm_queue_lock (q);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200312
313 if (PREDICT_FALSE (q->cursize + 1 == q->maxsize))
314 {
315 if (nowait)
316 {
Ping Yua4748942019-03-12 05:28:16 -0400317 svm_queue_unlock (q);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200318 return (-2);
319 }
320 while (q->cursize + 1 == q->maxsize)
Florin Coras99368312018-08-02 10:45:44 -0700321 svm_queue_wait_inline (q);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200322 }
323
324 tailp = (i8 *) (&q->data[0] + q->elsize * q->tail);
Dave Barach178cf492018-11-13 16:34:13 -0500325 clib_memcpy_fast (tailp, elem, q->elsize);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200326
327 q->tail++;
328 q->cursize++;
329
330 if (q->tail == q->maxsize)
331 q->tail = 0;
332
333 need_broadcast = (q->cursize == 1);
334
335 tailp = (i8 *) (&q->data[0] + q->elsize * q->tail);
Dave Barach178cf492018-11-13 16:34:13 -0500336 clib_memcpy_fast (tailp, elem2, q->elsize);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200337
338 q->tail++;
339 q->cursize++;
340
341 if (q->tail == q->maxsize)
342 q->tail = 0;
343
344 if (need_broadcast)
Florin Corasfea813a2019-12-27 10:26:56 -0800345 svm_queue_send_signal_inline (q, 1);
Florin Corasc470e222018-08-01 07:53:18 -0700346
Ping Yua4748942019-03-12 05:28:16 -0400347 svm_queue_unlock (q);
Klement Sekera8f2a4ea2017-05-04 06:15:18 +0200348
349 return 0;
350}
351
352/*
Florin Corase86a8ed2018-01-05 03:20:25 -0800353 * svm_queue_sub
Ed Warnickecb9cada2015-12-08 15:45:58 -0700354 */
Dave Barach371e4e12016-07-08 09:38:52 -0400355int
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100356svm_queue_sub (svm_queue_t * q, u8 * elem, svm_q_conditional_wait_t cond,
357 u32 time)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700358{
Dave Barach371e4e12016-07-08 09:38:52 -0400359 i8 *headp;
360 int need_broadcast = 0;
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100361 int rc = 0;
Dave Barach371e4e12016-07-08 09:38:52 -0400362
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100363 if (cond == SVM_Q_NOWAIT)
Dave Barach371e4e12016-07-08 09:38:52 -0400364 {
365 /* zero on success */
366 if (pthread_mutex_trylock (&q->mutex))
367 {
368 return (-1);
369 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700370 }
Dave Barach371e4e12016-07-08 09:38:52 -0400371 else
Ping Yua4748942019-03-12 05:28:16 -0400372 svm_queue_lock (q);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700373
Dave Barach371e4e12016-07-08 09:38:52 -0400374 if (PREDICT_FALSE (q->cursize == 0))
375 {
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100376 if (cond == SVM_Q_NOWAIT)
Dave Barach371e4e12016-07-08 09:38:52 -0400377 {
Ping Yua4748942019-03-12 05:28:16 -0400378 svm_queue_unlock (q);
Dave Barach371e4e12016-07-08 09:38:52 -0400379 return (-2);
380 }
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100381 else if (cond == SVM_Q_TIMEDWAIT)
Dave Barach371e4e12016-07-08 09:38:52 -0400382 {
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100383 while (q->cursize == 0 && rc == 0)
Florin Coras99368312018-08-02 10:45:44 -0700384 rc = svm_queue_timedwait_inline (q, time);
385
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100386 if (rc == ETIMEDOUT)
387 {
Ping Yua4748942019-03-12 05:28:16 -0400388 svm_queue_unlock (q);
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100389 return ETIMEDOUT;
390 }
391 }
392 else
393 {
394 while (q->cursize == 0)
Florin Coras99368312018-08-02 10:45:44 -0700395 svm_queue_wait_inline (q);
Dave Barach371e4e12016-07-08 09:38:52 -0400396 }
397 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700398
Dave Barach371e4e12016-07-08 09:38:52 -0400399 headp = (i8 *) (&q->data[0] + q->elsize * q->head);
Dave Barach178cf492018-11-13 16:34:13 -0500400 clib_memcpy_fast (elem, headp, q->elsize);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700401
Dave Barach371e4e12016-07-08 09:38:52 -0400402 q->head++;
Dave Barach68b0fb02017-02-28 15:15:56 -0500403 /* $$$$ JFC shouldn't this be == 0? */
Dave Barach371e4e12016-07-08 09:38:52 -0400404 if (q->cursize == q->maxsize)
405 need_broadcast = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700406
Dave Barach371e4e12016-07-08 09:38:52 -0400407 q->cursize--;
408
409 if (q->head == q->maxsize)
410 q->head = 0;
411
412 if (need_broadcast)
Florin Corasfea813a2019-12-27 10:26:56 -0800413 svm_queue_send_signal_inline (q, 0);
Dave Barach371e4e12016-07-08 09:38:52 -0400414
Ping Yua4748942019-03-12 05:28:16 -0400415 svm_queue_unlock (q);
Dave Barach371e4e12016-07-08 09:38:52 -0400416
417 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700418}
419
Dave Barach371e4e12016-07-08 09:38:52 -0400420int
Florin Corase86a8ed2018-01-05 03:20:25 -0800421svm_queue_sub2 (svm_queue_t * q, u8 * elem)
422{
423 int need_broadcast;
424 i8 *headp;
425
Ping Yua4748942019-03-12 05:28:16 -0400426 svm_queue_lock (q);
Florin Corase86a8ed2018-01-05 03:20:25 -0800427 if (q->cursize == 0)
428 {
Ping Yua4748942019-03-12 05:28:16 -0400429 svm_queue_unlock (q);
Florin Corase86a8ed2018-01-05 03:20:25 -0800430 return -1;
431 }
432
433 headp = (i8 *) (&q->data[0] + q->elsize * q->head);
Dave Barach178cf492018-11-13 16:34:13 -0500434 clib_memcpy_fast (elem, headp, q->elsize);
Florin Corase86a8ed2018-01-05 03:20:25 -0800435
436 q->head++;
437 need_broadcast = (q->cursize == q->maxsize / 2);
438 q->cursize--;
439
440 if (PREDICT_FALSE (q->head == q->maxsize))
441 q->head = 0;
Ping Yua4748942019-03-12 05:28:16 -0400442 svm_queue_unlock (q);
Florin Corase86a8ed2018-01-05 03:20:25 -0800443
444 if (need_broadcast)
Florin Corasfea813a2019-12-27 10:26:56 -0800445 svm_queue_send_signal_inline (q, 0);
Florin Corase86a8ed2018-01-05 03:20:25 -0800446
447 return 0;
448}
449
450int
451svm_queue_sub_raw (svm_queue_t * q, u8 * elem)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700452{
Florin Corasfea813a2019-12-27 10:26:56 -0800453 int need_broadcast;
Dave Barach371e4e12016-07-08 09:38:52 -0400454 i8 *headp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700455
Dave Barach371e4e12016-07-08 09:38:52 -0400456 if (PREDICT_FALSE (q->cursize == 0))
457 {
458 while (q->cursize == 0)
459 ;
460 }
461
462 headp = (i8 *) (&q->data[0] + q->elsize * q->head);
Dave Barach178cf492018-11-13 16:34:13 -0500463 clib_memcpy_fast (elem, headp, q->elsize);
Dave Barach371e4e12016-07-08 09:38:52 -0400464
Florin Corasfea813a2019-12-27 10:26:56 -0800465 need_broadcast = q->cursize == q->maxsize;
466
Florin Coras3c2fed52018-07-04 04:15:05 -0700467 q->head = (q->head + 1) % q->maxsize;
Dave Barach371e4e12016-07-08 09:38:52 -0400468 q->cursize--;
469
Florin Corasfea813a2019-12-27 10:26:56 -0800470 if (PREDICT_FALSE (need_broadcast))
471 svm_queue_send_signal_inline (q, 0);
472
Dave Barach371e4e12016-07-08 09:38:52 -0400473 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700474}
Dave Barach371e4e12016-07-08 09:38:52 -0400475
Florin Corasc470e222018-08-01 07:53:18 -0700476void
477svm_queue_set_producer_event_fd (svm_queue_t * q, int fd)
478{
479 q->producer_evtfd = fd;
480}
481
482void
483svm_queue_set_consumer_event_fd (svm_queue_t * q, int fd)
484{
485 q->consumer_evtfd = fd;
486}
487
Dave Barach371e4e12016-07-08 09:38:52 -0400488/*
489 * fd.io coding-style-patch-verification: ON
490 *
491 * Local Variables:
492 * eval: (c-set-style "gnu")
493 * End:
494 */