From e2195ac505bd423d3d2f973bbe94da1c78296aa6 Mon Sep 17 00:00:00 2001 From: Alex Williams Date: Fri, 31 Aug 2018 11:35:07 -0700 Subject: transport: Add blocking recv calls to uhd-dpdk This adds an internal wait queue API to uhd-dpdk. Socket configuration requests had their blocking calls re-implemented on top of this API, and it is also used to service requests to wait on RX packets (w/ timeout). The wait API involves a multi-producer, single-consumer queue per I/O thread (waiter_ring), with a condition variable used for sleeping. The data structure is shared between user thread and I/O thread, and because timeouts make resource release time non-deterministic, we use reference counting on the shared resource. One reference is generated by the user thread and passed to the I/O thread to consume. A user thread that still needs the data after waking must get() another reference, to postpone the destruction of the resource until it is done. Timeouts are based on CLOCK_MONOTONIC. For recv, a timeout of 0 indicates blocking indefinitely, and a negative timeout indicates no timeout is desired. Also drop timeout for closing sockets in uhd-dpdk. The timeout would allow a user thread to pre-empt the I/O thread's cleanup process. The user thread would free data structures the I/O thread still needed to function. Since this timeout is superfluous anyway, let's just get rid of it. Also add some more input checking and error reporting. --- host/lib/transport/uhd-dpdk/uhd_dpdk_wait.h | 62 +++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 host/lib/transport/uhd-dpdk/uhd_dpdk_wait.h (limited to 'host/lib/transport/uhd-dpdk/uhd_dpdk_wait.h') diff --git a/host/lib/transport/uhd-dpdk/uhd_dpdk_wait.h b/host/lib/transport/uhd-dpdk/uhd_dpdk_wait.h new file mode 100644 index 000000000..465608810 --- /dev/null +++ b/host/lib/transport/uhd-dpdk/uhd_dpdk_wait.h @@ -0,0 +1,62 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// +#ifndef _UHD_DPDK_WAIT_H_ +#define _UHD_DPDK_WAIT_H_ + +#include "uhd_dpdk_ctx.h" +#include + +enum uhd_dpdk_wait_type { + UHD_DPDK_WAIT_SIMPLE, + UHD_DPDK_WAIT_RX, + UHD_DPDK_WAIT_TX_BUF, + UHD_DPDK_WAIT_TYPE_COUNT +}; + +struct uhd_dpdk_wait_req { + enum uhd_dpdk_wait_type reason; + struct uhd_dpdk_socket *sock; + pthread_cond_t cond; + pthread_mutex_t mutex; + rte_atomic32_t refcnt; /* free resources only when refcnt = 0 */ +}; + +static inline void uhd_dpdk_waiter_put(struct uhd_dpdk_wait_req *req) +{ + if (rte_atomic32_dec_and_test(&req->refcnt)) { + rte_free(req); + } +} + +static inline void uhd_dpdk_waiter_get(struct uhd_dpdk_wait_req *req) +{ + rte_atomic32_inc(&req->refcnt); +} + +/* + * Attempt to wake thread + * Re-enqueue waiter to thread's waiter_queue if fail + */ +int _uhd_dpdk_waiter_wake(struct uhd_dpdk_wait_req *req, + struct uhd_dpdk_thread *t); + +/* + * Allocates wait request and sets refcnt to 1 + */ +struct uhd_dpdk_wait_req *uhd_dpdk_waiter_alloc(enum uhd_dpdk_wait_type reason); + +/* + * Block and send wait request to thread t + */ +int uhd_dpdk_waiter_wait(struct uhd_dpdk_wait_req *req, int timeout, + struct uhd_dpdk_thread *t); + +/* + * Block and submit config request to thread t + */ +int uhd_dpdk_config_req_submit(struct uhd_dpdk_config_req *req, + int timeout, struct uhd_dpdk_thread *t); +#endif /* _UHD_DPDK_WAIT_H_ */ -- cgit v1.2.3