From: hanlin Date: Tue, 19 May 2020 09:34:17 +0000 (+0800) Subject: vcl: nest vcl_mq_epfd to support epoll_wait without high CPU usage X-Git-Tag: v21.01-rc0~372 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=4266d4d5ff96043f6d2fbd217e97eddf8916e346;p=vpp.git vcl: nest vcl_mq_epfd to support epoll_wait without high CPU usage Now, libc epfd and vls epfd are independent and can only epoll_wait independently without timeout, then app calling epoll_wait will occupy high CPU. So we nest vcl_mq_epfd into libc epfd when using eventfd with VPP, and then we can only epoll_wait libc epfd with specified timeout. Type: feature Signed-off-by: hanlin Change-Id: I6b6e0f501c769e186714bfbc187cfaed2533b4c2 Signed-off-by: hanlin --- diff --git a/src/vcl/ldp.c b/src/vcl/ldp.c index 091c7e5cff4..e3e6dfac1c6 100644 --- a/src/vcl/ldp.c +++ b/src/vcl/ldp.c @@ -80,6 +80,7 @@ typedef struct ldp_worker_ctx_ * Epoll state */ u8 epoll_wait_vcl; + u8 mq_epfd_added; int vcl_mq_epfd; } ldp_worker_ctx_t; @@ -2344,17 +2345,132 @@ done: return rv; } +static inline int +ldp_epoll_pwait_eventfd (int epfd, struct epoll_event *events, + int maxevents, int timeout, const sigset_t * sigmask) +{ + ldp_worker_ctx_t *ldpw = ldp_worker_get_current (); + int libc_epfd, rv = 0, num_ev; + vls_handle_t ep_vlsh; + + if ((errno = -ldp_init ())) + return -1; + + if (PREDICT_FALSE (!events || (timeout < -1))) + { + errno = EFAULT; + return -1; + } + + if (epfd == ldpw->vcl_mq_epfd) + return libc_epoll_pwait (epfd, events, maxevents, timeout, sigmask); + + ep_vlsh = ldp_fd_to_vlsh (epfd); + if (PREDICT_FALSE (ep_vlsh == VLS_INVALID_HANDLE)) + { + LDBG (0, "epfd %d: bad ep_vlsh %d!", epfd, ep_vlsh); + errno = EBADFD; + return -1; + } + + libc_epfd = vls_attr (ep_vlsh, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0); + if (PREDICT_FALSE (!libc_epfd)) + { + u32 size = sizeof (epfd); + + LDBG (1, "epfd %d, vep_vlsh %d calling libc_epoll_create1: " + "EPOLL_CLOEXEC", epfd, ep_vlsh); + libc_epfd = libc_epoll_create1 (EPOLL_CLOEXEC); + if (libc_epfd < 0) + { + rv = libc_epfd; + goto done; + } + + rv = vls_attr (ep_vlsh, VPPCOM_ATTR_SET_LIBC_EPFD, &libc_epfd, &size); + if (rv < 0) + { + errno = -rv; + rv = -1; + goto done; + } + } + if (PREDICT_FALSE (libc_epfd <= 0)) + { + errno = -libc_epfd; + rv = -1; + goto done; + } + + if (PREDICT_FALSE (!ldpw->mq_epfd_added)) + { + struct epoll_event e = { 0 }; + e.events = EPOLLIN; + e.data.fd = ldpw->vcl_mq_epfd; + if (libc_epoll_ctl (libc_epfd, EPOLL_CTL_ADD, ldpw->vcl_mq_epfd, &e) < + 0) + { + LDBG (0, "epfd %d, add libc mq epoll fd %d to libc epoll fd %d", + epfd, ldpw->vcl_mq_epfd, libc_epfd); + rv = -1; + goto done; + } + ldpw->mq_epfd_added = 1; + } + + rv = vls_epoll_wait (ep_vlsh, events, maxevents, 0); + if (rv > 0) + goto done; + else if (rv < 0) + { + errno = -rv; + rv = -1; + goto done; + } + + rv = libc_epoll_pwait (libc_epfd, events, maxevents, timeout, sigmask); + if (rv <= 0) + goto done; + for (int i = 0; i < rv; i++) + { + if (events[i].data.fd == ldpw->vcl_mq_epfd) + { + /* We should remove mq epoll fd from events. */ + rv--; + if (i != rv) + { + events[i].events = events[rv].events; + events[i].data.u64 = events[rv].data.u64; + } + num_ev = vls_epoll_wait (ep_vlsh, &events[rv], maxevents - rv, 0); + if (PREDICT_TRUE (num_ev > 0)) + rv += num_ev; + break; + } + } + +done: + return rv; +} + int epoll_pwait (int epfd, struct epoll_event *events, int maxevents, int timeout, const sigset_t * sigmask) { - return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask); + if (vls_use_eventfd ()) + return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout, + sigmask); + else + return ldp_epoll_pwait (epfd, events, maxevents, timeout, sigmask); } int epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout) { - return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL); + if (vls_use_eventfd ()) + return ldp_epoll_pwait_eventfd (epfd, events, maxevents, timeout, NULL); + else + return ldp_epoll_pwait (epfd, events, maxevents, timeout, NULL); } int diff --git a/src/vcl/vcl_locked.c b/src/vcl/vcl_locked.c index ae9c9762dc1..19522c05d61 100644 --- a/src/vcl/vcl_locked.c +++ b/src/vcl/vcl_locked.c @@ -1381,6 +1381,12 @@ vls_app_create (char *app_name) return VPPCOM_OK; } +unsigned char +vls_use_eventfd (void) +{ + return vcm->cfg.use_mq_eventfd; +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vcl/vcl_locked.h b/src/vcl/vcl_locked.h index 2c8f2115230..18b341b11ca 100644 --- a/src/vcl/vcl_locked.h +++ b/src/vcl/vcl_locked.h @@ -50,6 +50,7 @@ vcl_session_handle_t vlsh_to_sh (vls_handle_t vlsh); vcl_session_handle_t vlsh_to_session_index (vls_handle_t vlsh); vls_handle_t vls_session_index_to_vlsh (uint32_t session_index); int vls_app_create (char *app_name); +unsigned char vls_use_eventfd (void); #endif /* SRC_VCL_VCL_LOCKED_H_ */