aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/transport/uhd-dpdk/uhd_dpdk_wait.c
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/transport/uhd-dpdk/uhd_dpdk_wait.c')
-rw-r--r--host/lib/transport/uhd-dpdk/uhd_dpdk_wait.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/host/lib/transport/uhd-dpdk/uhd_dpdk_wait.c b/host/lib/transport/uhd-dpdk/uhd_dpdk_wait.c
new file mode 100644
index 000000000..c00eaa3c4
--- /dev/null
+++ b/host/lib/transport/uhd-dpdk/uhd_dpdk_wait.c
@@ -0,0 +1,114 @@
+//
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+#include "uhd_dpdk_wait.h"
+
+int _uhd_dpdk_waiter_wake(struct uhd_dpdk_wait_req *req,
+ struct uhd_dpdk_thread *t)
+{
+ int stat = pthread_mutex_trylock(&req->mutex);
+ if (stat) {
+ if (rte_ring_full(t->waiter_ring)) {
+ RTE_LOG(ERR, USER2, "%s: Could not lock req mutex\n", __func__);
+ return -ENOBUFS;
+ } else {
+ req->reason = UHD_DPDK_WAIT_SIMPLE;
+ rte_ring_enqueue(t->waiter_ring, req);
+ return -EAGAIN;
+ }
+ }
+ stat = pthread_cond_signal(&req->cond);
+ if (stat)
+ RTE_LOG(ERR, USER2, "%s: Could not signal req cond\n", __func__);
+ pthread_mutex_unlock(&req->mutex);
+ uhd_dpdk_waiter_put(req);
+ return stat;
+}
+
+struct uhd_dpdk_wait_req *uhd_dpdk_waiter_alloc(enum uhd_dpdk_wait_type reason)
+{
+ struct uhd_dpdk_wait_req *req;
+ req = (struct uhd_dpdk_wait_req *) rte_zmalloc(NULL, sizeof(*req), 0);
+ if (!req)
+ return NULL;
+
+ pthread_mutex_init(&req->mutex, NULL);
+ pthread_condattr_t condattr;
+ pthread_condattr_init(&condattr);
+ pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
+ pthread_cond_init(&req->cond, &condattr);
+ rte_atomic32_set(&req->refcnt, 1);
+ req->reason = reason;
+ return req;
+}
+
+static inline void uhd_dpdk_waiter_prepare(struct uhd_dpdk_wait_req *req)
+{
+ pthread_mutex_lock(&req->mutex);
+ /* Get a reference here, to be consumed by other thread (handshake) */
+ uhd_dpdk_waiter_get(req);
+}
+
+static inline int uhd_dpdk_waiter_submit(struct uhd_dpdk_wait_req *req,
+ int timeout)
+{
+ int retval = 0;
+ if (timeout < 0) {
+ retval = pthread_cond_wait(&req->cond, &req->mutex);
+ } else {
+ struct timespec timeout_spec;
+ clock_gettime(CLOCK_MONOTONIC, &timeout_spec);
+ timeout_spec.tv_sec += timeout/1000000;
+ timeout_spec.tv_nsec += (timeout % 1000000)*1000;
+ if (timeout_spec.tv_nsec > 1000000000) {
+ timeout_spec.tv_sec++;
+ timeout_spec.tv_nsec -= 1000000000;
+ }
+ retval = pthread_cond_timedwait(&req->cond, &req->mutex, &timeout_spec);
+ }
+ return retval;
+}
+
+int uhd_dpdk_waiter_wait(struct uhd_dpdk_wait_req *req, int timeout,
+ struct uhd_dpdk_thread *t)
+{
+ int ret;
+ if (!req || !t)
+ return -EINVAL;
+
+ uhd_dpdk_waiter_prepare(req);
+
+ ret = rte_ring_enqueue(t->waiter_ring, req);
+ if (ret) {
+ uhd_dpdk_waiter_put(req);
+ pthread_mutex_unlock(&req->mutex);
+ return ret;
+ }
+
+ uhd_dpdk_waiter_submit(req, timeout);
+ pthread_mutex_unlock(&req->mutex);
+ return 0;
+}
+
+int uhd_dpdk_config_req_submit(struct uhd_dpdk_config_req *req,
+ int timeout, struct uhd_dpdk_thread *t)
+{
+ int ret;
+ if (!req || !t)
+ return -EINVAL;
+
+ uhd_dpdk_waiter_prepare(req->waiter);
+
+ ret = rte_ring_enqueue(t->sock_req_ring, req);
+ if (ret) {
+ uhd_dpdk_waiter_put(req->waiter);
+ pthread_mutex_unlock(&req->waiter->mutex);
+ return ret;
+ }
+
+ uhd_dpdk_waiter_submit(req->waiter, timeout);
+ pthread_mutex_unlock(&req->waiter->mutex);
+ return 0;
+}