[PATCH] osmo-sip-connector[master]: evpoll: Implement poll with ppoll and map select to poll..

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Holger Freyther gerrit-no-reply at lists.osmocom.org
Wed Mar 8 09:32:53 UTC 2017


Hello Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/1987

to look at the new patch set (#2).

evpoll: Implement poll with ppoll and map select to poll..

To avoid the semantic difference with POLLERR, implement polling
with ppoll. We use ppoll as the timeout is closer to select and
copy fds around and clear it after.

Passing empty/unused struct pollfd to the kernel is a bit wasteful
but something we have to deal with right now but I will try to
fix that up now.

Change-Id: I12d3af23315d762a8fcd83255647a3df6aff7166
---
M src/evpoll.c
1 file changed, 84 insertions(+), 36 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-sip-connector refs/changes/87/1987/2

diff --git a/src/evpoll.c b/src/evpoll.c
index 087955f..a646801 100644
--- a/src/evpoll.c
+++ b/src/evpoll.c
@@ -18,46 +18,90 @@
  *
  */
 
+#define _GNU_SOURCE
 #include "evpoll.h"
+#include "logging.h"
 
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/core/select.h>
 #include <osmocom/core/timer.h>
+#include <osmocom/core/utils.h>
 
-#include <sys/select.h>
+#include <poll.h>
 
-/* based on osmo_select_main GPLv2+ so combined compatible with AGPLv3+ */
+#include <sys/poll.h>
+#include <sys/time.h>
+
+#define my_ts_cmp(left, right, cmp) \
+		(((left)->tv_sec cmp (right)->tv_sec) ?			\
+			((left)->tv_nsec cmp (right)->tv_sec) :		\
+			((left)->tv_sec cmp (right)->tv_sec))
+
+static struct pollfd g_fds[FD_SETSIZE];
+
+static struct timespec *timers_nearest() {
+	static struct timespec ts;
+	struct timeval *tv;
+
+	tv = osmo_timers_nearest();
+	if (!tv)
+		return NULL;
+
+	ts.tv_sec = tv->tv_sec;
+	ts.tv_nsec = tv->tv_usec * 1000;
+	return &ts;
+}
+
+#define MAYBE_CLEAR(fd, set, rflag)				\
+		if (FD_ISSET(fd, set))				\
+			if ((g_fds[fd].revents & rflag) == 0)	\
+				FD_CLR(fd, set);
+
 int evpoll(struct pollfd *fds, nfds_t nfds, int timeout)
 {
-	struct timeval *tv, null_tv = { 0, 0} , poll_tv;
+	struct timespec *ts, null_ts = { 0, 0} , poll_ts;
 	fd_set readset, writeset, exceptset;
-	int maxfd, rc, i;
+	int maxfd, i, rc, all_nfds;
 
 	FD_ZERO(&readset);
 	FD_ZERO(&writeset);
 	FD_ZERO(&exceptset);
 
-	/* prepare read and write fdsets */
 	maxfd = osmo_fd_fill_fds(&readset, &writeset, &exceptset);
+	all_nfds = maxfd;
 
+	/* disable all fds */
+	for (i = 0; i < ARRAY_SIZE(g_fds); ++i) {
+		g_fds[i].fd = -1;
+		g_fds[i].revents = 0;
+	}
+
+	/* copy the osmocom selectors to pollfds */
+	for (i = 0; i <= maxfd; ++i) {
+		if (!FD_ISSET(i, &readset)
+			&& !FD_ISSET(i, &writeset) && !FD_ISSET(i, &exceptset))
+			continue;
+
+		g_fds[i].fd = i;
+		g_fds[i].events = 0;
+		if (FD_ISSET(i, &readset))
+			g_fds[i].events |= POLLIN;
+		if (FD_ISSET(i, &writeset))
+			g_fds[i].events |= POLLOUT;
+	}
+
+	/* copy the remaining ones */
 	for (i = 0; i < nfds; ++i) {
 		if (fds[i].fd < 0)
 			continue;
-		if ((fds[i].events & (POLLIN | POLLOUT | POLLPRI)) == 0)
+		if (fds[i].fd >= ARRAY_SIZE(g_fds)) {
+			LOGP(DAPP, LOGL_ERROR, "Can not poll fd=%d.\n", fds[i].fd);
 			continue;
-
-		/* copy events. Not sure why glib maps PRI to exceptionset */
-		if (fds[i].events & POLLIN)
-			FD_SET(fds[i].fd, &readset);
-		if (fds[i].events & POLLOUT)
-			FD_SET(fds[i].fd, &writeset);
-		if (fds[i].events & POLLPRI)
-			FD_SET(fds[i].fd, &exceptset);
-
-		if (fds[i].fd > maxfd)
-			maxfd = fds[i].fd;
+		}
+		if (fds[i].fd > all_nfds)
+			all_nfds = fds[i].fd;
+		g_fds[fds[i].fd] = fds[i];
 	}
-
 
 	osmo_timers_check();
 	osmo_timers_prepare();
@@ -65,23 +109,24 @@
 	/*
 	 * 0 == wake-up immediately
 	 * -1 == block forever.. which will depend on our timers
+	 * and convert
 	 */
 	if (timeout == 0) {
-		tv = &null_tv;
+		ts = &null_ts;
 	} else if (timeout == -1) {
-		tv = osmo_timers_nearest();
+		ts = timers_nearest();
 	} else {
-		poll_tv.tv_sec = timeout / 1000;
-		poll_tv.tv_usec = (timeout % 1000) * 1000;
+		poll_ts.tv_sec = timeout / 1000;
+		poll_ts.tv_nsec = (timeout % 1000) * 1000 * 1000;
 
-		tv = osmo_timers_nearest();
-		if (!tv)
-			tv = &poll_tv;
-		else if (timercmp(&poll_tv, tv, <))
-			tv = &poll_tv;
+		ts = timers_nearest();
+		if (!ts)
+			ts = &poll_ts;
+		else if (my_ts_cmp(&poll_ts, ts, <))
+			ts = &poll_ts;
 	}
 
-	rc = select(maxfd+1, &readset, &writeset, &exceptset, tv);
+	rc = ppoll(g_fds, all_nfds + 1, ts, NULL);
 	if (rc < 0)
 		return 0;
 
@@ -89,21 +134,24 @@
 	osmo_timers_update();
 
 	/* call registered callback functions */
+	for (i = 0; i <= maxfd; ++i) {
+		MAYBE_CLEAR(i, &readset, POLLIN)
+		MAYBE_CLEAR(i, &writeset, POLLOUT)
+		MAYBE_CLEAR(i, &exceptset, POLLERR)
+	}
 	osmo_fd_disp_fds(&readset, &writeset, &exceptset);
 
 	for (i = 0; i < nfds; ++i) {
-		fds[i].revents = 0;
 
-		if (fds[i].fd < 0)
+		if (fds[i].fd < 0) {
+			fds[i].revents = 0;
 			continue;
+		}
 
-		if (FD_ISSET(fds[i].fd, &readset))
-			fds[i].revents = POLLIN | POLLERR;
-		if (FD_ISSET(fds[i].fd, &writeset))
-			fds[i].revents |= POLLOUT;
-		if (FD_ISSET(fds[i].fd, &exceptset))
-			fds[i].revents |= POLLPRI;
+		fds[i].revents  = g_fds[fds[i].fd].revents;
 	}
 
 	return rc;
 }
+
+#undef MAYBE_CLEAR

-- 
To view, visit https://gerrit.osmocom.org/1987
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I12d3af23315d762a8fcd83255647a3df6aff7166
Gerrit-PatchSet: 2
Gerrit-Project: osmo-sip-connector
Gerrit-Branch: master
Gerrit-Owner: Holger Freyther <holger at freyther.de>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list