]> Zhao Yanbai Git Server - minix.git/commitdiff
RS: use IPC filters to do a timed receive 00/3100/2
authorDavid van Moolenbroek <david@minix3.org>
Thu, 16 Jul 2015 05:59:53 +0000 (07:59 +0200)
committerDavid van Moolenbroek <david@minix3.org>
Wed, 16 Sep 2015 15:31:10 +0000 (15:31 +0000)
Change-Id: I28df9920d8a65b47f3cf974ed9c5eb3174479d8a

minix/servers/rs/proto.h
minix/servers/rs/utility.c

index 4e9e088b8de4472ba7a448f610411da1dcf94e38..b88086d07fff76be33dae1b784924947fc714fc4 100644 (file)
@@ -131,7 +131,7 @@ char* srv_to_string_gen(struct rproc *rp, int is_verbose);
 char* srv_upd_to_string(struct rprocupd *rpupd);
 int rs_asynsend(struct rproc *rp, message *m_ptr, int no_reply);
 int rs_receive_ticks(endpoint_t src, message *m_ptr,
-    int *status_ptr, int ticks);
+    int *status_ptr, clock_t ticks);
 void reply(endpoint_t who, struct rproc *rp, message *m_ptr);
 void late_reply(struct rproc *rp, int code);
 int rs_isokendpt(endpoint_t endpoint, int *proc);
index e8a4011b358458a71bc70fb5d3ed30bb66fbb597..5810f25cceec7776f2e43d9cc737c62799ad0783 100644 (file)
@@ -219,10 +219,62 @@ int rs_asynsend(struct rproc *rp, message *m_ptr, int no_reply)
  *                          rs_receive_ticks                                *
  *===========================================================================*/
 int rs_receive_ticks(endpoint_t src, message *m_ptr,
-    int *status_ptr, int ticks)
+    int *status_ptr, clock_t ticks)
 {
-  printf("RS: rs_receive_ticks not implemented\n");
-  return ENOSYS;
+/* IPC receive with timeout.  Implemented with IPC filters.  The timer
+ * management logic comes from the tickdelay(3) implementation.
+ */
+  ipc_filter_el_t ipc_filter[2];
+  clock_t time_left, uptime;
+  int r, s, status;
+
+  /* Use IPC filters to receive from the provided source and CLOCK only.
+   * We make the hard assumption that RS did not already have IPC filters set.
+   */
+  memset(ipc_filter, 0, sizeof(ipc_filter));
+  ipc_filter[0].flags = IPCF_MATCH_M_SOURCE;
+  ipc_filter[0].m_source = CLOCK;
+  ipc_filter[1].flags = IPCF_MATCH_M_SOURCE;
+  ipc_filter[1].m_source = src;
+
+  if ((s = sys_statectl(SYS_STATE_ADD_IPC_WL_FILTER, ipc_filter,
+    sizeof(ipc_filter))) != OK)
+      panic("RS: rs_receive_ticks: setting IPC filter failed: %d", s);
+
+  /* Set a new alarm, and get information about the previous alarm. */
+  if ((s = sys_setalarm2(ticks, FALSE, &time_left, &uptime)) != OK)
+      panic("RS: rs_receive_ticks: setting alarm failed: %d", s);
+
+  /* Receive a message from either the provided source or CLOCK. */
+  while ((r = ipc_receive(ANY, m_ptr, &status)) == OK &&
+    m_ptr->m_source == CLOCK) {
+      /* Ignore early clock notifications. */
+      if (m_ptr->m_type == NOTIFY_MESSAGE &&
+        m_ptr->m_notify.timestamp >= uptime + ticks)
+          break;
+  }
+
+  /* Reinstate the previous alarm, if any. Do this in any case. */
+  if (time_left != TMR_NEVER) {
+      if (time_left > ticks)
+          time_left -= ticks;
+      else
+          time_left = 1; /* force an alarm */
+
+      (void)sys_setalarm(time_left, FALSE);
+  }
+
+  /* Clear the IPC filters. */
+  if ((s = sys_statectl(SYS_STATE_CLEAR_IPC_FILTERS, NULL, 0)) != OK)
+      panic("RS: rs_receive_ticks: setting IPC filter failed: %d", s);
+
+  /* If the last received message was from CLOCK, we timed out. */
+  if (r == OK && m_ptr->m_source == CLOCK)
+      return ENOTREADY;
+
+  if (status_ptr != NULL)
+      *status_ptr = status;
+  return r;
 }
 
 /*===========================================================================*