diff --git a/kernel/channel.c b/kernel/channel.c index 27ad372..ce342d2 100644 --- a/kernel/channel.c +++ b/kernel/channel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -80,6 +81,7 @@ static void kmsg_reply_error( unsigned long *lock_flags) { msg->msg_status = KMSG_REPLY_SENT; + msg->msg_sender_port->p_status = PORT_READY; msg->msg_result = status; thread_awaken(msg->msg_sender_thread); spin_unlock_irqrestore(&msg->msg_lock, *lock_flags); @@ -95,6 +97,7 @@ static struct kmsg *get_next_msg( spin_lock_irqsave(&msg->msg_lock, lock_flags); if (msg->msg_status == KMSG_WAIT_RECEIVE) { msg->msg_status = KMSG_WAIT_REPLY; + msg->msg_sender_port->p_status = PORT_REPLY_BLOCKED; return msg; } @@ -149,17 +152,24 @@ extern kern_status_t channel_recv_msg( struct task *sender = msg->msg_sender_thread->tr_parent; struct task *receiver = self->tr_parent; + struct vm_region *src = sender->t_address_space, + *dst = receiver->t_address_space; + unsigned long f; + vm_region_lock_pair_irqsave(src, dst, &f); + kern_status_t status = vm_region_memmove_v( - receiver->t_address_space, + dst, 0, out_msg->msg_data, out_msg->msg_data_count, - sender->t_address_space, + src, 0, msg->msg_req.msg_data, msg->msg_req.msg_data_count, VM_REGION_COPY_ALL, NULL); + vm_region_unlock_pair_irqrestore(src, dst, f); + if (status != KERN_OK) { kmsg_reply_error(msg, status, &msg_lock_flags); return status; @@ -208,17 +218,24 @@ extern kern_status_t channel_reply_msg( /* the task that is about to send the response */ struct task *sender = self->tr_parent; + struct vm_region *src = sender->t_address_space, + *dst = receiver->t_address_space; + unsigned long f; + vm_region_lock_pair_irqsave(src, dst, &f); + kern_status_t status = vm_region_memmove_v( - receiver->t_address_space, + dst, 0, msg->msg_resp.msg_data, msg->msg_resp.msg_data_count, - sender->t_address_space, + src, 0, resp->msg_data, resp->msg_data_count, VM_REGION_COPY_ALL, NULL); + vm_region_unlock_pair_irqrestore(src, dst, f); + if (status != KERN_OK) { kmsg_reply_error(msg, status, &msg_lock_flags); return status; @@ -262,17 +279,24 @@ extern kern_status_t channel_read_msg( return KERN_INVALID_ARGUMENT; } + struct vm_region *src_region + = msg->msg_sender_thread->tr_parent->t_address_space; + + unsigned long f; + vm_region_lock_pair_irqsave(src_region, dest_region, &f); + kern_status_t status = vm_region_memmove_v( dest_region, 0, dest_iov, dest_iov_count, - msg->msg_sender_thread->tr_parent->t_address_space, + src_region, offset, msg->msg_req.msg_data, msg->msg_req.msg_data_count, VM_REGION_COPY_ALL, nr_read); + vm_region_unlock_pair_irqrestore(src_region, dest_region, f); spin_unlock_irqrestore(&msg->msg_lock, msg_lock_flags);