kernel: fix channel locking and status update issues

This commit is contained in:
2026-02-26 19:42:12 +00:00
parent eb8758bc5e
commit 2073cad97b

View File

@@ -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);