kernel: fix channel locking and status update issues
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
#include <kernel/channel.h>
|
#include <kernel/channel.h>
|
||||||
#include <kernel/msg.h>
|
#include <kernel/msg.h>
|
||||||
|
#include <kernel/port.h>
|
||||||
#include <kernel/util.h>
|
#include <kernel/util.h>
|
||||||
#include <kernel/vm-region.h>
|
#include <kernel/vm-region.h>
|
||||||
|
|
||||||
@@ -80,6 +81,7 @@ static void kmsg_reply_error(
|
|||||||
unsigned long *lock_flags)
|
unsigned long *lock_flags)
|
||||||
{
|
{
|
||||||
msg->msg_status = KMSG_REPLY_SENT;
|
msg->msg_status = KMSG_REPLY_SENT;
|
||||||
|
msg->msg_sender_port->p_status = PORT_READY;
|
||||||
msg->msg_result = status;
|
msg->msg_result = status;
|
||||||
thread_awaken(msg->msg_sender_thread);
|
thread_awaken(msg->msg_sender_thread);
|
||||||
spin_unlock_irqrestore(&msg->msg_lock, *lock_flags);
|
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);
|
spin_lock_irqsave(&msg->msg_lock, lock_flags);
|
||||||
if (msg->msg_status == KMSG_WAIT_RECEIVE) {
|
if (msg->msg_status == KMSG_WAIT_RECEIVE) {
|
||||||
msg->msg_status = KMSG_WAIT_REPLY;
|
msg->msg_status = KMSG_WAIT_REPLY;
|
||||||
|
msg->msg_sender_port->p_status = PORT_REPLY_BLOCKED;
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,17 +152,24 @@ extern kern_status_t channel_recv_msg(
|
|||||||
struct task *sender = msg->msg_sender_thread->tr_parent;
|
struct task *sender = msg->msg_sender_thread->tr_parent;
|
||||||
struct task *receiver = self->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(
|
kern_status_t status = vm_region_memmove_v(
|
||||||
receiver->t_address_space,
|
dst,
|
||||||
0,
|
0,
|
||||||
out_msg->msg_data,
|
out_msg->msg_data,
|
||||||
out_msg->msg_data_count,
|
out_msg->msg_data_count,
|
||||||
sender->t_address_space,
|
src,
|
||||||
0,
|
0,
|
||||||
msg->msg_req.msg_data,
|
msg->msg_req.msg_data,
|
||||||
msg->msg_req.msg_data_count,
|
msg->msg_req.msg_data_count,
|
||||||
VM_REGION_COPY_ALL,
|
VM_REGION_COPY_ALL,
|
||||||
NULL);
|
NULL);
|
||||||
|
vm_region_unlock_pair_irqrestore(src, dst, f);
|
||||||
|
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
kmsg_reply_error(msg, status, &msg_lock_flags);
|
kmsg_reply_error(msg, status, &msg_lock_flags);
|
||||||
return status;
|
return status;
|
||||||
@@ -208,17 +218,24 @@ extern kern_status_t channel_reply_msg(
|
|||||||
/* the task that is about to send the response */
|
/* the task that is about to send the response */
|
||||||
struct task *sender = self->tr_parent;
|
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(
|
kern_status_t status = vm_region_memmove_v(
|
||||||
receiver->t_address_space,
|
dst,
|
||||||
0,
|
0,
|
||||||
msg->msg_resp.msg_data,
|
msg->msg_resp.msg_data,
|
||||||
msg->msg_resp.msg_data_count,
|
msg->msg_resp.msg_data_count,
|
||||||
sender->t_address_space,
|
src,
|
||||||
0,
|
0,
|
||||||
resp->msg_data,
|
resp->msg_data,
|
||||||
resp->msg_data_count,
|
resp->msg_data_count,
|
||||||
VM_REGION_COPY_ALL,
|
VM_REGION_COPY_ALL,
|
||||||
NULL);
|
NULL);
|
||||||
|
vm_region_unlock_pair_irqrestore(src, dst, f);
|
||||||
|
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
kmsg_reply_error(msg, status, &msg_lock_flags);
|
kmsg_reply_error(msg, status, &msg_lock_flags);
|
||||||
return status;
|
return status;
|
||||||
@@ -262,17 +279,24 @@ extern kern_status_t channel_read_msg(
|
|||||||
return KERN_INVALID_ARGUMENT;
|
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(
|
kern_status_t status = vm_region_memmove_v(
|
||||||
dest_region,
|
dest_region,
|
||||||
0,
|
0,
|
||||||
dest_iov,
|
dest_iov,
|
||||||
dest_iov_count,
|
dest_iov_count,
|
||||||
msg->msg_sender_thread->tr_parent->t_address_space,
|
src_region,
|
||||||
offset,
|
offset,
|
||||||
msg->msg_req.msg_data,
|
msg->msg_req.msg_data,
|
||||||
msg->msg_req.msg_data_count,
|
msg->msg_req.msg_data_count,
|
||||||
VM_REGION_COPY_ALL,
|
VM_REGION_COPY_ALL,
|
||||||
nr_read);
|
nr_read);
|
||||||
|
vm_region_unlock_pair_irqrestore(src_region, dest_region, f);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&msg->msg_lock, msg_lock_flags);
|
spin_unlock_irqrestore(&msg->msg_lock, msg_lock_flags);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user