Commit 709dbf8d authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan

dispatch-loop: Add non-blocking synchronous IPC recv.

We need this for the dispatch loop. A receiver needs to be able
to poll on synchronous IPC channels (in addition to async
channels).
parent eb910308
......@@ -190,6 +190,12 @@ static inline int lcd_syscall_sync_recv(cptr_t endpoint)
return lcd_syscall_one_arg(LCD_SYSCALL_SYNC_RECV, cptr_val(endpoint));
}
static inline int lcd_syscall_sync_poll_recv(cptr_t endpoint)
{
return lcd_syscall_one_arg(LCD_SYSCALL_SYNC_POLL_RECV,
cptr_val(endpoint));
}
static inline int lcd_syscall_sync_call(cptr_t endpoint)
{
return lcd_syscall_one_arg(LCD_SYSCALL_SYNC_CALL, cptr_val(endpoint));
......
......@@ -898,6 +898,10 @@ int __lcd_send(struct lcd *caller, cptr_t endpoint);
* @endpoint: cptr to sync IPC endpoint
*/
int __lcd_recv(struct lcd *caller, cptr_t endpoint);
/**
* __lcd_poll_recv -- Non-blocking sync ipc receive
*/
int __lcd_poll_recv(struct lcd *caller, cptr_t endpoint);
/**
* __lcd_call -- Sync IPC call
* @caller: LCD doing the calling
......
......@@ -126,6 +126,18 @@ int lcd_sync_send(cptr_t endpoint);
*/
int lcd_sync_recv(cptr_t endpoint);
/**
* lcd_sync_poll_recv -- non-blocking synchronous IPC receive
* @endpoint: cptr to the IPC channel
*
* This is like lcd_sync_recv, but if there is no sender waiting, immediately
* returns, rather than blocking.
*
* If there is no sender (i.e., nothing was received), returns
* -EWOULDBLOCK.
*/
int lcd_sync_poll_recv(cptr_t endpoint);
/**
* lcd_sync_call -- synchronous IPC call
* @endpoint: cptr to a capability for a synchronous IPC channel/endpoint
......
......@@ -18,6 +18,7 @@ enum lcd_syscall {
LCD_SYSCALL_EXIT,
LCD_SYSCALL_SYNC_SEND,
LCD_SYSCALL_SYNC_RECV,
LCD_SYSCALL_SYNC_POLL_RECV,
LCD_SYSCALL_SYNC_CALL,
LCD_SYSCALL_SYNC_REPLY,
LCD_SYSCALL_CREATE_SYNC_EP,
......
......@@ -56,6 +56,11 @@ int lcd_sync_recv(cptr_t endpoint)
return __lcd_recv(current->lcd, endpoint);
}
int lcd_sync_poll_recv(cptr_t endpoint)
{
return __lcd_poll_recv(current->lcd, endpoint);
}
int lcd_sync_call(cptr_t endpoint)
{
return __lcd_call(current->lcd, endpoint);
......
......@@ -70,6 +70,13 @@ lcd_sync_recv(cptr_t endpoint)
return lcd_syscall_sync_recv(endpoint);
}
int
LIBLCD_FUNC_ATTR
lcd_sync_poll_recv(cptr_t endpoint)
{
return lcd_syscall_sync_poll_recv(endpoint);
}
int
LIBLCD_FUNC_ATTR
lcd_sync_call(cptr_t endpoint)
......
......@@ -455,7 +455,8 @@ fail1:
}
static int do_recv(struct lcd *receiver, struct cnode *cnode,
struct lcd_sync_endpoint *ep)
struct lcd_sync_endpoint *ep,
int polling)
{
int ret;
struct lcd *sender;
......@@ -464,6 +465,11 @@ static int do_recv(struct lcd *receiver, struct cnode *cnode,
debug_dump_utcb(receiver);
if (list_empty(&ep->senders)) {
/*
* If we're polling, don't wait
*/
if (polling)
return -EWOULDBLOCK;
/*
* No one sending; put myself in ep's receiver list
*/
......@@ -561,7 +567,7 @@ int __lcd_recv(struct lcd *caller, cptr_t endpoint)
goto fail1;
}
/* do_recv does put on ep */
ret = do_recv(caller, cnode, ep);
ret = do_recv(caller, cnode, ep, 0);
if (ret) {
LCD_ERR("failed receive");
goto fail2;
......@@ -575,6 +581,36 @@ fail1:
return ret;
}
int __lcd_poll_recv(struct lcd *caller, cptr_t endpoint)
{
struct lcd_sync_endpoint *ep;
struct cnode *cnode;
int ret;
/*
* Look up and lock endpoint
*/
ret = __lcd_get_sync_endpoint(caller, endpoint, &cnode, &ep);
if (ret) {
LCD_DEBUG(LCD_DEBUG_ERR,
"ep lookup failed for cptr 0x%lx", cptr_val(endpoint));
goto fail1;
}
/* do_recv does put on ep */
ret = do_recv(caller, cnode, ep, 1);
if (ret) {
if (ret != -EWOULDBLOCK)
LCD_ERR("failed receive");
goto fail2;
}
return 0;
fail2:
__lcd_put_sync_endpoint(caller, cnode, ep);
fail1:
return ret;
}
int __lcd_call(struct lcd *caller, cptr_t endpoint)
{
struct lcd_sync_endpoint *ep;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment