diff options
Diffstat (limited to 'proc/ipc.c')
| -rw-r--r-- | proc/ipc.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/proc/ipc.c b/proc/ipc.c new file mode 100644 index 0000000..db1233d --- /dev/null +++ b/proc/ipc.c @@ -0,0 +1,116 @@ +#include "ipc.h" +#include "api/error.h" +#include "proc/process.h" +#include "sys/objdir.h" +#include "jove.h" + +inline pid_t port_get_owner(struct port *port) +{ + return port->owner; +} + +inline struct port *port_get_send_target(struct port *port) +{ + return port->send_target; +} + +inline struct port *port_get_recv_target(struct port *port) +{ + return port->recv_target; +} + +inline void port_set_recv_target(struct port *port, struct port *target) +{ + port->recv_target = target; +} + +inline bool port_poll_send(struct port *port) { return port_get_send_target(port) != 0; } +inline bool port_poll_recv(struct port *port) { return obj_peektype(port->recv) != JOVE_OBJ_NONE; } + +int port_take_send(struct port *port, jove_owned_obj_t *dest_obj) +{ + jove_owned_obj_t *send_obj = obj_take(&port->send); + + if(!port_get_send_target(port)) { + ipc_klogf("Port %p does not have mail to send\n", port); + obj_release(send_obj); + return -EEMPTY; + } + + ipc_klogf("Taking obj from %i into obj %p\n", port->send_target, dest_obj); + + objdir_swapobj(send_obj, dest_obj); + port->send_target = 0; + obj_release(send_obj); + return 0; +} + +struct port *port_take_recv(struct port *port, jove_owned_obj_t *dest_obj) +{ + errno = 0; + jove_owned_obj_t *recv_obj = obj_take(&port->recv); + + //Validate that the port has an object in the recv object. + if(obj_gettype(recv_obj) == JOVE_OBJ_NONE) { + ipc_klogf("Port %p does not have mail\n", port); + obj_release(recv_obj); + errno = EEMPTY; + return NULL; + } + + ipc_klogf("Taking obj from %i into obj %p\n", port->recv_target, dest_obj); + + objdir_swapobj(recv_obj, dest_obj); + struct port *recv_port = port_get_recv_target(port); + port_set_recv_target(port, (void*)-1); + obj_release(recv_obj); + + return recv_port; +} + +int port_send(struct port *source, struct port *target, jove_owned_obj_t *sent_obj) +{ + jove_owned_obj_t *target_recv_obj = obj_take(&target->recv); + + //Validate that the target is full or is not accepting from this port. + if((port_get_recv_target(target) != 0 && port_get_recv_target(target) != source) + || port_poll_recv(target)) { + + obj_release(target_recv_obj); + ipc_klogf("Target %p is full. Sending to send buffer. \n", target); + + jove_owned_obj_t *source_send_obj = obj_take(&source->send); + + //Validate that the send buffer has space. + if(port_get_send_target(source)) { + ipc_klogf("Source %p is full\n", source); + obj_release(source_send_obj); + return -EFULL; + } + objdir_swapobj(source_send_obj, sent_obj); + source->send_target = target; + + obj_release(source_send_obj); + return 1; + } + + objdir_swapobj(target_recv_obj, sent_obj); + target->recv_target = source; + + obj_release(target_recv_obj); + return 0; +} + +int port_recv(struct port *source, struct port *target) +{ + jove_owned_obj_t *source_send_obj = obj_take(&source->send); + jove_owned_obj_t *target_recv_obj = obj_take(&target->recv); + + objdir_swapobj(source_send_obj, target_recv_obj); + target->recv_target = source; + source->send_target = NULL; + + obj_release(target_recv_obj); + obj_release(source_send_obj); + return 0; +} |
