2018-10-06 06:52:47 -07:00
|
|
|
// User-level IPC library routines
|
|
|
|
|
|
|
|
#include <inc/lib.h>
|
|
|
|
|
|
|
|
// Receive a value via IPC and return it.
|
|
|
|
// If 'pg' is nonnull, then any page sent by the sender will be mapped at
|
|
|
|
// that address.
|
|
|
|
// If 'from_env_store' is nonnull, then store the IPC sender's envid in
|
|
|
|
// *from_env_store.
|
|
|
|
// If 'perm_store' is nonnull, then store the IPC sender's page permission
|
|
|
|
// in *perm_store (this is nonzero iff a page was successfully
|
|
|
|
// transferred to 'pg').
|
|
|
|
// If the system call fails, then store 0 in *fromenv and *perm (if
|
|
|
|
// they're nonnull) and return the error.
|
|
|
|
// Otherwise, return the value sent by the sender
|
|
|
|
//
|
|
|
|
// Hint:
|
|
|
|
// Use 'thisenv' to discover the value and who sent it.
|
|
|
|
// If 'pg' is null, pass sys_ipc_recv a value that it will understand
|
|
|
|
// as meaning "no page". (Zero is not the right value, since that's
|
|
|
|
// a perfectly valid place to map a page.)
|
|
|
|
int32_t
|
|
|
|
ipc_recv(envid_t *from_env_store, void *pg, int *perm_store)
|
|
|
|
{
|
2019-05-05 22:08:12 -07:00
|
|
|
int return_code;
|
|
|
|
if((return_code = sys_ipc_recv(pg ? pg : (void*) ~0)) < 0)
|
|
|
|
return return_code;
|
|
|
|
|
|
|
|
if(from_env_store) *from_env_store = thisenv->env_ipc_from;
|
|
|
|
if(perm_store) *perm_store = thisenv->env_ipc_perm;
|
|
|
|
|
|
|
|
return thisenv->env_ipc_value;
|
2018-10-06 06:52:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Send 'val' (and 'pg' with 'perm', if 'pg' is nonnull) to 'toenv'.
|
|
|
|
// This function keeps trying until it succeeds.
|
|
|
|
// It should panic() on any error other than -E_IPC_NOT_RECV.
|
|
|
|
//
|
|
|
|
// Hint:
|
|
|
|
// Use sys_yield() to be CPU-friendly.
|
|
|
|
// If 'pg' is null, pass sys_ipc_try_send a value that it will understand
|
|
|
|
// as meaning "no page". (Zero is not the right value.)
|
|
|
|
void
|
|
|
|
ipc_send(envid_t to_env, uint32_t val, void *pg, int perm)
|
|
|
|
{
|
2019-05-05 22:08:12 -07:00
|
|
|
int return_code = -E_IPC_NOT_RECV;
|
|
|
|
while(return_code == -E_IPC_NOT_RECV) {
|
|
|
|
return_code = sys_ipc_try_send(to_env, val, pg ? pg : (void*) ~0, perm);
|
|
|
|
sys_yield();
|
|
|
|
}
|
|
|
|
if(return_code != 0) panic("failed to send\n");
|
2018-10-06 06:52:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Find the first environment of the given type. We'll use this to
|
|
|
|
// find special environments.
|
|
|
|
// Returns 0 if no such environment exists.
|
|
|
|
envid_t
|
|
|
|
ipc_find_env(enum EnvType type)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < NENV; i++)
|
|
|
|
if (envs[i].env_type == type)
|
|
|
|
return envs[i].env_id;
|
|
|
|
return 0;
|
|
|
|
}
|