On Wed, 2013-01-23 at 17:52 +0100, Svante Signell wrote:
> On Wed, 2013-01-23 at 00:52 +0100, Samuel Thibault wrote:
> > Svante Signell, le Tue 22 Jan 2013 20:53:06 +0100, a écrit :

> Since there was a lot of concerns about code duplication I introduced a
> helper function _wait_for_replies(), splitting out the union definitions
> and the _mach_msg() call.

Introduced another helper function: _io_select_request()
The patch does the following:
1) Create another helper function: _io_select_request() (good enough name?)
2) Sets got to -1 in case of errors and always return got in both helper
functions.

(Hopefully I got the call by value and call by reference issues right)

The patch is made against hurdselect_step1_2.c.

Next step will be to introduce the three cases: DELAY POLL, SELECT
before adding the needed changes for POLL.  

--- hurdselect_step1_2.c	2013-01-23 17:23:30.000000000 +0100
+++ hurdselect_step1_3.c	2013-01-24 11:40:13.000000000 +0100
@@ -42,7 +42,77 @@ struct dfd
   mach_port_t reply_port;
 };
 
-/* Helper function */
+/* Helper functions */
+int _io_select_request (int nfds, int firstfd, int lastfd,
+		       error_t err, mach_port_t *portset, struct dfd *d)
+{
+  *portset = MACH_PORT_NULL;
+  int i, got = 0;
+
+  for (i = firstfd; i <= lastfd; ++i)
+    if (d[i].type)
+      {
+	int type = d[i].type;
+	d[i].reply_port = __mach_reply_port ();
+	err = __io_select (d[i].io_port, d[i].reply_port, 0, &type);
+	switch (err)
+	  {
+	  case MACH_RCV_TIMED_OUT:
+	    /* No immediate response.  This is normal.  */
+	    err = 0;
+	    if (firstfd == lastfd)
+	      /* When there's a single descriptor, we don't need a
+		 portset, so just pretend we have one, but really
+		 use the single reply port.  */
+	      *portset = d[i].reply_port;
+	    else if (got == 0)
+	      /* We've got multiple reply ports, so we need a port set to
+		 multiplex them.  */
+	      {
+		/* We will wait again for a reply later.  */
+		if (*portset == MACH_PORT_NULL)
+		  /* Create the portset to receive all the replies on.  */
+		  err = __mach_port_allocate (__mach_task_self (),
+					      MACH_PORT_RIGHT_PORT_SET,
+					      portset);
+		if (! err)
+		  /* Put this reply port in the port set.  */
+		  __mach_port_move_member (__mach_task_self (),
+					   d[i].reply_port, *portset);
+	      }
+	    break;
+
+	  default:
+	    /* No other error should happen.  Callers of select
+	       don't expect to see errors, so we simulate
+	       readiness of the erring object and the next call
+	       hopefully will get the error again.  */
+	    type = SELECT_ALL;
+	    /* FALLTHROUGH */
+
+	  case 0:
+	    /* We got an answer.  */
+	    if ((type & SELECT_ALL) == 0)
+	      /* Bogus answer; treat like an error, as a fake positive.  */
+	      type = SELECT_ALL;
+
+	    /* This port is already ready already.  */
+	    d[i].type &= type;
+	    d[i].type |= SELECT_RETURNED;
+	    ++got;
+	    break;
+	  } /* switch (err) */
+	_hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
+      } /* if (d[i].type) */
+ 
+  if (err)
+    {
+      errno = err;
+      got = -1;
+    }
+  return got;
+} /* _io_select_request() */
+
 int _wait_for_replies (int nfds, int firstfd, int lastfd, mach_msg_timeout_t to,
 		       error_t err, mach_port_t portset, struct dfd *d,
 		       const struct timespec *timeout, const sigset_t *sigmask,
@@ -200,10 +270,9 @@ int _wait_for_replies (int nfds, int fir
 	if (sigmask)
 	  __sigprocmask (SIG_SETMASK, oset, NULL);
 	errno = err;
-	return -1;
+	got = -1;
       }
-    else
-      return got;
+    return got;
   } /* _wait_for_replies() */
 
 /* Check the first NFDS descriptors either in POLLFDS (if nonnnull) or in
@@ -402,65 +471,10 @@ _hurd_select (int nfds,
        We are just a pure timeout.  */
     portset = __mach_reply_port ();
   else /* POLL || SELECT */
-    {
-      portset = MACH_PORT_NULL;
-
-      for (i = firstfd; i <= lastfd; ++i)
-	if (d[i].type)
-	  {
-	    int type = d[i].type;
-	    d[i].reply_port = __mach_reply_port ();
-	    err = __io_select (d[i].io_port, d[i].reply_port, 0, &type);
-	    switch (err)
-	      {
-	      case MACH_RCV_TIMED_OUT:
-		/* No immediate response.  This is normal.  */
-		err = 0;
-		if (firstfd == lastfd)
-		  /* When there's a single descriptor, we don't need a
-		     portset, so just pretend we have one, but really
-		     use the single reply port.  */
-		  portset = d[i].reply_port;
-		else if (got == 0)
-		  /* We've got multiple reply ports, so we need a port set to
-		     multiplex them.  */
-		  {
-		    /* We will wait again for a reply later.  */
-		    if (portset == MACH_PORT_NULL)
-		      /* Create the portset to receive all the replies on.  */
-		      err = __mach_port_allocate (__mach_task_self (),
-						  MACH_PORT_RIGHT_PORT_SET,
-						  &portset);
-		    if (! err)
-		      /* Put this reply port in the port set.  */
-		      __mach_port_move_member (__mach_task_self (),
-					       d[i].reply_port, portset);
-		  }
-		break;
-
-	      default:
-		/* No other error should happen.  Callers of select
-		   don't expect to see errors, so we simulate
-		   readiness of the erring object and the next call
-		   hopefully will get the error again.  */
-		type = SELECT_ALL;
-		/* FALLTHROUGH */
-
-	      case 0:
-		/* We got an answer.  */
-		if ((type & SELECT_ALL) == 0)
-		  /* Bogus answer; treat like an error, as a fake positive.  */
-		  type = SELECT_ALL;
-
-		/* This port is already ready already.  */
-		d[i].type &= type;
-		d[i].type |= SELECT_RETURNED;
-		++got;
-		break;
-	      }
-	    _hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
-	  }
-    } /* POLL || SELECT */
+    got =  _io_select_request (nfds, firstfd, lastfd,
+			       err, &portset, d);
+  if (got == -1)
+    return -1;
 
   got = _wait_for_replies (nfds, firstfd, lastfd, to, 
 			   err, portset, d,

Reply via email to