From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 856F1C6AE for ; Tue, 5 May 2015 07:40:18 +0200 (CEST) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga103.fm.intel.com with ESMTP; 04 May 2015 22:40:18 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,370,1427785200"; d="scan'208";a="566352029" Received: from shvmail01.sh.intel.com ([10.239.29.42]) by orsmga003.jf.intel.com with ESMTP; 04 May 2015 22:40:17 -0700 Received: from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com [10.239.29.89]) by shvmail01.sh.intel.com with ESMTP id t455eEm6019232; Tue, 5 May 2015 13:40:14 +0800 Received: from shecgisg004.sh.intel.com (localhost [127.0.0.1]) by shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP id t455eBPE029011; Tue, 5 May 2015 13:40:13 +0800 Received: (from cliang18@localhost) by shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id t455eB58029007; Tue, 5 May 2015 13:40:11 +0800 From: Cunming Liang To: dev@dpdk.org Date: Tue, 5 May 2015 13:39:38 +0800 Message-Id: <1430804386-28949-3-git-send-email-cunming.liang@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1430804386-28949-1-git-send-email-cunming.liang@intel.com> References: <1425012976-10173-1-git-send-email-cunming.liang@intel.com> <1430804386-28949-1-git-send-email-cunming.liang@intel.com> Cc: shemming@brocade.com Subject: [dpdk-dev] [PATCH v7 02/10] eal/linux: add rte_epoll_wait/ctl support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 May 2015 05:40:19 -0000 The patch adds 'rte_epoll_wait' and 'rte_epoll_ctl' for async event wakeup. It defines 'struct rte_epoll_event' as the event param. The 'op' uses the same enum as epoll_wait/ctl does. The epoll event support to carry a raw user data and to register a callback which is exectuted during wakeup. Signed-off-by: Cunming Liang --- v7 changes - split v6[4/8] into two patches, one for epoll event(this one) another for rx intr(next patch) - introduce rte_epoll_event definition - rte_epoll_wait/ctl for more generic RTE epoll API v6 changes - split rte_intr_wait_rx_pkt into two function, wait and set. - rewrite rte_intr_rx_wait/rte_intr_rx_set to remove queue visibility on eal. - rte_intr_rx_wait to support multiplexing. - allow epfd as input to support flexible event fd combination. lib/librte_eal/linuxapp/eal/eal_interrupts.c | 97 ++++++++++++++++++++++ .../linuxapp/eal/include/exec-env/rte_interrupts.h | 66 ++++++++++++++- lib/librte_eal/linuxapp/eal/rte_eal_version.map | 3 + 3 files changed, 165 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c index 66deda2..b641745 100644 --- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c +++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c @@ -69,6 +69,8 @@ #define EAL_INTR_EPOLL_WAIT_FOREVER (-1) +static RTE_DEFINE_PER_LCORE(int, _epfd) = -1; /**< epoll fd per thread */ + /** * union for pipe fds. */ @@ -859,3 +861,98 @@ rte_eal_intr_init(void) return -ret; } +static void +eal_epoll_process_event(struct epoll_event *evs, int n, + struct rte_epoll_event *events) +{ + int i; + struct rte_epoll_event *rev; + for (i = 0; i < n; i++) { + rev = (struct rte_epoll_event *)evs[i].data.ptr; + if (rev) { + events[i].fd = rev->fd; + events[i].event = rev->event; + events[i].data = rev->data; + if (rev->cb_fun) + rev->cb_fun(rev->fd, rev->cb_arg); + } + } +} + +static inline int +eal_init_tls_epfd(void) +{ + int pfd = epoll_create(255); + if (pfd < 0) { + RTE_LOG(ERR, EAL, + "Cannot create epoll instance\n"); + return -1; + } + return pfd; +} + +int +rte_intr_tls_epfd(void) +{ + if (RTE_PER_LCORE(_epfd) == -1) + RTE_PER_LCORE(_epfd) = eal_init_tls_epfd(); + + return RTE_PER_LCORE(_epfd); +} + +int +rte_epoll_wait(int epfd, struct rte_epoll_event *events, + int maxevents, int timeout) +{ + struct epoll_event evs[maxevents]; + int rc; + + if (!events) { + RTE_LOG(ERR, EAL, "rte_epoll_event can't be NULL\n"); + return -1; + } + + /* using per thread epoll fd */ + if (epfd == RTE_EPOLL_PER_THREAD) + epfd = rte_intr_tls_epfd(); + + rc = epoll_wait(epfd, evs, maxevents, timeout); + if (likely(rc > 0)) + /* epoll_wait has at least one fd ready to read */ + eal_epoll_process_event(evs, rc, events); + else if (rc < 0) { + /* epoll_wait fail */ + RTE_LOG(ERR, EAL, "epoll_wait returns with fail %s\n", + strerror(errno)); + rc = -1; + } + + return rc; +} + +int +rte_epoll_ctl(int epfd, int op, int fd, + struct rte_epoll_event *event) +{ + struct epoll_event ev; + + if (!event) { + RTE_LOG(ERR, EAL, "rte_epoll_event can't be NULL\n"); + return -1; + } + + /* using per thread epoll fd */ + if (epfd == RTE_EPOLL_PER_THREAD) + epfd = rte_intr_tls_epfd(); + + event->fd = fd; /* ignore fd in rev */ + ev.data.ptr = (void *)event; + ev.events = event->event; + if (epoll_ctl(epfd, op, fd, &ev) < 0) { + RTE_LOG(ERR, EAL, "Error op %d fd %d epoll_ctl, %s\n", + op, fd, strerror(errno)); + return -1; + } + + return 0; +} diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h index e1f4a7a..af405cf 100644 --- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h +++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_interrupts.h @@ -50,7 +50,19 @@ enum rte_intr_handle_type { RTE_INTR_HANDLE_MAX }; -struct rte_epoll_event; +#define RTE_INTR_EVENT_ADD 1UL +#define RTE_INTR_EVENT_DEL 2UL + +typedef void (*rte_intr_event_cb_t)(int fd, void *arg); + +/** interrupt epoll event obj, taken by epoll_event.ptr */ +struct rte_epoll_event { + int fd; /**< OUT: event fd */ + uint32_t event; /**< event type */ + void *data; /**< User data */ + rte_intr_event_cb_t cb_fun; /**< IN: callback fun */ + void *cb_arg; /**< IN: callback arg */ +}; /** Handle for interrupts. */ struct rte_intr_handle { @@ -69,4 +81,56 @@ struct rte_intr_handle { int *intr_vec; /**< intr vector number array */ }; +#define RTE_EPOLL_PER_THREAD -1 /**< to hint using per thread epfd */ + +/** + * It waits for events on the epoll instance. + * + * @param epfd + * Epoll instance fd on which the caller wait for events. + * @param events + * Memory area contains the events that will be available for the caller. + * @param maxevents + * Up to maxevents are returned, must greater than zero. + * @param timeout + * Specifying a timeout of -1 causes a block indefinitely. + * Specifying a timeout equal to zero cause to return immediately. + * @return + * - On success, returns the number of available event. + * - On failure, a negative value. + */ +int +rte_epoll_wait(int epfd, struct rte_epoll_event *events, + int maxevents, int timeout); + +/** + * It performs control operations on epoll instance referred by the epfd. + * It requests that the operation op be performed for the target fd. + * + * @param epfd + * Epoll instance fd on which the caller perform control operations. + * @param op + * The operation be performed for the target fd. + * @param fd + * The target fd on which the control ops perform. + * @param event + * Describes the object linked to the fd. + * Note: The caller must take care the object deletion after CTL_DEL. + * @return + * - On success, zero. + * - On failure, a negative value. + */ +int +rte_epoll_ctl(int epfd, int op, int fd, + struct rte_epoll_event *event); + +/** + * The function returns the per thread epoll instance. + * + * @return + * epfd the epoll instance refered to. + */ +int +rte_intr_tls_epfd(void); + #endif /* _RTE_LINUXAPP_INTERRUPTS_H_ */ diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index 7e850a9..840002e 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -52,6 +52,8 @@ DPDK_2.0 { rte_eal_vdev_init; rte_eal_vdev_uninit; rte_eal_wait_lcore; + rte_epoll_ctl; + rte_epoll_wait; rte_exit; rte_get_hpet_cycles; rte_get_hpet_hz; @@ -61,6 +63,7 @@ DPDK_2.0 { rte_intr_callback_unregister; rte_intr_disable; rte_intr_enable; + rte_intr_tls_epfd; rte_log; rte_log_add_in_history; rte_log_cur_msg_loglevel; -- 1.8.1.4