ipc: end multiprocess thread during cleanup
[dpdk.git] / lib / eventdev / rte_eventdev.h
index 1b11d45..25fb7c8 100644 (file)
@@ -299,6 +299,16 @@ struct rte_event;
  * the content of this field is implementation dependent.
  */
 
+#define RTE_EVENT_DEV_CAP_MAINTENANCE_FREE (1ULL << 10)
+/**< Event device *does not* require calls to rte_event_maintain().
+ * An event device that does not set this flag requires calls to
+ * rte_event_maintain() during periods when neither
+ * rte_event_dequeue_burst() nor rte_event_enqueue_burst() are called
+ * on a port. This will allow the event device to perform internal
+ * processing, such as flushing buffered events, return credits to a
+ * global pool, or process signaling related to load balancing.
+ */
+
 /* Event device priority levels */
 #define RTE_EVENT_DEV_PRIORITY_HIGHEST   0
 /**< Highest priority expressed across eventdev subsystem
@@ -709,6 +719,38 @@ rte_event_queue_attr_get(uint8_t dev_id, uint8_t queue_id, uint32_t attr_id,
  *
  *  @see rte_event_port_setup(), rte_event_port_link()
  */
+#define RTE_EVENT_PORT_CFG_HINT_PRODUCER       (1ULL << 2)
+/**< Hint that this event port will primarily enqueue events to the system.
+ * A PMD can optimize its internal workings by assuming that this port is
+ * primarily going to enqueue NEW events.
+ *
+ * Note that this flag is only a hint, so PMDs must operate under the
+ * assumption that any port can enqueue an event with any type of op.
+ *
+ *  @see rte_event_port_setup()
+ */
+#define RTE_EVENT_PORT_CFG_HINT_CONSUMER       (1ULL << 3)
+/**< Hint that this event port will primarily dequeue events from the system.
+ * A PMD can optimize its internal workings by assuming that this port is
+ * primarily going to consume events, and not enqueue FORWARD or RELEASE
+ * events.
+ *
+ * Note that this flag is only a hint, so PMDs must operate under the
+ * assumption that any port can enqueue an event with any type of op.
+ *
+ *  @see rte_event_port_setup()
+ */
+#define RTE_EVENT_PORT_CFG_HINT_WORKER         (1ULL << 4)
+/**< Hint that this event port will primarily pass existing events through.
+ * A PMD can optimize its internal workings by assuming that this port is
+ * primarily going to FORWARD events, and not enqueue NEW or RELEASE events
+ * often.
+ *
+ * Note that this flag is only a hint, so PMDs must operate under the
+ * assumption that any port can enqueue an event with any type of op.
+ *
+ *  @see rte_event_port_setup()
+ */
 
 /** Event port configuration structure */
 struct rte_event_port_conf {
@@ -1193,7 +1235,7 @@ struct rte_event {
 #define RTE_EVENT_ETH_RX_ADAPTER_CAP_OVERRIDE_FLOW_ID  0x4
 /**< The application can override the adapter generated flow ID in the
  * event. This flow ID can be specified when adding an ethdev Rx queue
- * to the adapter using the ev member of struct rte_event_eth_rx_adapter
+ * to the adapter using the ev.flow_id member.
  * @see struct rte_event_eth_rx_adapter_queue_conf::ev
  * @see struct rte_event_eth_rx_adapter_queue_conf::rx_queue_flags
  */
@@ -1734,7 +1776,6 @@ int rte_event_dev_selftest(uint8_t dev_id);
  *    - ENOMEM - no appropriate memory area found in which to create memzone
  *    - ENAMETOOLONG - mempool name requested is too long.
  */
-__rte_experimental
 struct rte_mempool *
 rte_event_vector_pool_create(const char *name, unsigned int n,
                             unsigned int cache_size, uint16_t nb_elem,
@@ -1747,28 +1788,32 @@ __rte_event_enqueue_burst(uint8_t dev_id, uint8_t port_id,
                          const struct rte_event ev[], uint16_t nb_events,
                          const event_enqueue_burst_t fn)
 {
-       const struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+       const struct rte_event_fp_ops *fp_ops;
+       void *port;
 
+       fp_ops = &rte_event_fp_ops[dev_id];
+       port = fp_ops->data[port_id];
 #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
-       if (dev_id >= RTE_EVENT_MAX_DEVS || !rte_eventdevs[dev_id].attached) {
+       if (dev_id >= RTE_EVENT_MAX_DEVS ||
+           port_id >= RTE_EVENT_MAX_PORTS_PER_DEV) {
                rte_errno = EINVAL;
                return 0;
        }
 
-       if (port_id >= dev->data->nb_ports) {
+       if (port == NULL) {
                rte_errno = EINVAL;
                return 0;
        }
 #endif
-       rte_eventdev_trace_enq_burst(dev_id, port_id, ev, nb_events, fn);
+       rte_eventdev_trace_enq_burst(dev_id, port_id, ev, nb_events, (void *)fn);
        /*
         * Allow zero cost non burst mode routine invocation if application
         * requests nb_events as const one
         */
        if (nb_events == 1)
-               return (*dev->enqueue)(dev->data->ports[port_id], ev);
+               return (fp_ops->enqueue)(port, ev);
        else
-               return fn(dev->data->ports[port_id], ev, nb_events);
+               return fn(port, ev, nb_events);
 }
 
 /**
@@ -1818,10 +1863,11 @@ static inline uint16_t
 rte_event_enqueue_burst(uint8_t dev_id, uint8_t port_id,
                        const struct rte_event ev[], uint16_t nb_events)
 {
-       const struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+       const struct rte_event_fp_ops *fp_ops;
 
+       fp_ops = &rte_event_fp_ops[dev_id];
        return __rte_event_enqueue_burst(dev_id, port_id, ev, nb_events,
-                                        dev->enqueue_burst);
+                                        fp_ops->enqueue_burst);
 }
 
 /**
@@ -1869,10 +1915,11 @@ static inline uint16_t
 rte_event_enqueue_new_burst(uint8_t dev_id, uint8_t port_id,
                            const struct rte_event ev[], uint16_t nb_events)
 {
-       const struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+       const struct rte_event_fp_ops *fp_ops;
 
+       fp_ops = &rte_event_fp_ops[dev_id];
        return __rte_event_enqueue_burst(dev_id, port_id, ev, nb_events,
-                                        dev->enqueue_new_burst);
+                                        fp_ops->enqueue_new_burst);
 }
 
 /**
@@ -1920,10 +1967,11 @@ static inline uint16_t
 rte_event_enqueue_forward_burst(uint8_t dev_id, uint8_t port_id,
                                const struct rte_event ev[], uint16_t nb_events)
 {
-       const struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+       const struct rte_event_fp_ops *fp_ops;
 
+       fp_ops = &rte_event_fp_ops[dev_id];
        return __rte_event_enqueue_burst(dev_id, port_id, ev, nb_events,
-                                        dev->enqueue_forward_burst);
+                                        fp_ops->enqueue_forward_burst);
 }
 
 /**
@@ -1996,15 +2044,19 @@ static inline uint16_t
 rte_event_dequeue_burst(uint8_t dev_id, uint8_t port_id, struct rte_event ev[],
                        uint16_t nb_events, uint64_t timeout_ticks)
 {
-       struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+       const struct rte_event_fp_ops *fp_ops;
+       void *port;
 
+       fp_ops = &rte_event_fp_ops[dev_id];
+       port = fp_ops->data[port_id];
 #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
-       if (dev_id >= RTE_EVENT_MAX_DEVS || !rte_eventdevs[dev_id].attached) {
+       if (dev_id >= RTE_EVENT_MAX_DEVS ||
+           port_id >= RTE_EVENT_MAX_PORTS_PER_DEV) {
                rte_errno = EINVAL;
                return 0;
        }
 
-       if (port_id >= dev->data->nb_ports) {
+       if (port == NULL) {
                rte_errno = EINVAL;
                return 0;
        }
@@ -2015,11 +2067,80 @@ rte_event_dequeue_burst(uint8_t dev_id, uint8_t port_id, struct rte_event ev[],
         * requests nb_events as const one
         */
        if (nb_events == 1)
-               return (*dev->dequeue)(dev->data->ports[port_id], ev,
-                                      timeout_ticks);
+               return (fp_ops->dequeue)(port, ev, timeout_ticks);
        else
-               return (*dev->dequeue_burst)(dev->data->ports[port_id], ev,
-                                            nb_events, timeout_ticks);
+               return (fp_ops->dequeue_burst)(port, ev, nb_events,
+                                              timeout_ticks);
+}
+
+#define RTE_EVENT_DEV_MAINT_OP_FLUSH          (1 << 0)
+/**< Force an immediately flush of any buffered events in the port,
+ * potentially at the cost of additional overhead.
+ *
+ * @see rte_event_maintain()
+ */
+
+/**
+ * Maintain an event device.
+ *
+ * This function is only relevant for event devices which do not have
+ * the @ref RTE_EVENT_DEV_CAP_MAINTENANCE_FREE flag set. Such devices
+ * require an application thread using a particular port to
+ * periodically call rte_event_maintain() on that port during periods
+ * which it is neither attempting to enqueue events to nor dequeue
+ * events from the port. rte_event_maintain() is a low-overhead
+ * function and should be called at a high rate (e.g., in the
+ * application's poll loop).
+ *
+ * No port may be left unmaintained.
+ *
+ * At the application thread's convenience, rte_event_maintain() may
+ * (but is not required to) be called even during periods when enqueue
+ * or dequeue functions are being called, at the cost of a slight
+ * increase in overhead.
+ *
+ * rte_event_maintain() may be called on event devices which have set
+ * @ref RTE_EVENT_DEV_CAP_MAINTENANCE_FREE, in which case it is a
+ * no-operation.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param port_id
+ *   The identifier of the event port.
+ * @param op
+ *   0, or @ref RTE_EVENT_DEV_MAINT_OP_FLUSH.
+ * @return
+ *  - 0 on success.
+ *  - -EINVAL if *dev_id*,  *port_id*, or *op* is invalid.
+ *
+ * @see RTE_EVENT_DEV_CAP_MAINTENANCE_FREE
+ */
+__rte_experimental
+static inline int
+rte_event_maintain(uint8_t dev_id, uint8_t port_id, int op)
+{
+       const struct rte_event_fp_ops *fp_ops;
+       void *port;
+
+       fp_ops = &rte_event_fp_ops[dev_id];
+       port = fp_ops->data[port_id];
+#ifdef RTE_LIBRTE_EVENTDEV_DEBUG
+       if (dev_id >= RTE_EVENT_MAX_DEVS ||
+           port_id >= RTE_EVENT_MAX_PORTS_PER_DEV)
+               return -EINVAL;
+
+       if (port == NULL)
+               return -EINVAL;
+
+       if (op & (~RTE_EVENT_DEV_MAINT_OP_FLUSH))
+               return -EINVAL;
+#endif
+       rte_eventdev_trace_maintain(dev_id, port_id, op);
+
+       if (fp_ops->maintain != NULL)
+               fp_ops->maintain(port, op);
+
+       return 0;
 }
 
 #ifdef __cplusplus