RS: use IPC filters to do a timed receive

Change-Id: I28df9920d8a65b47f3cf974ed9c5eb3174479d8a
This commit is contained in:
David van Moolenbroek 2015-07-16 07:59:53 +02:00
parent fb6bd596bf
commit f16b761d2a
2 changed files with 56 additions and 4 deletions

View 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);

View 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;
}
/*===========================================================================*