[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
Tue Mar 7 14:12:33 UTC 2017


Review at  https://gerrit.osmocom.org/1987

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/1

diff --git a/src/evpoll.c b/src/evpoll.c
index 087955f..291d0b5 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, osmo_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, &osmo_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: newchange
Gerrit-Change-Id: I12d3af23315d762a8fcd83255647a3df6aff7166
Gerrit-PatchSet: 1
Gerrit-Project: osmo-sip-connector
Gerrit-Branch: master
Gerrit-Owner: Holger Freyther <holger at freyther.de>



More information about the gerrit-log mailing list