修复ipc超时错误的问题

This commit is contained in:
zhangzheng
2023-11-28 13:46:37 +08:00
parent 5d0fe31b54
commit 6ff6d6e594
3 changed files with 112 additions and 78 deletions

View File

@@ -128,11 +128,10 @@ typedef struct thread
slist_head_t futex_node; //!< futex使用
msg_buf_t msg; //!< 每个线程独有的消息缓存区
slist_head_t wait_node; //!< 节点
mword_t ipc_times; //!< ipc时间
thread_t *last_send_th; //!< 当前线程上次接收到谁的数据
umword_t user_id; //!< 接收到的user_id
msg_buf_t msg; //!< 每个线程独有的消息缓存区
slist_head_t wait_send_head; //!< 等待头,那些节点等待给当前线程发送数据
thread_t *last_send_th; //!< 当前线程上次接收到谁的数据
umword_t user_id; //!< 接收到的user_id
enum thread_state status; //!< 线程状态
enum thread_ipc_state ipc_status; //!< ipc状态

View File

@@ -47,6 +47,22 @@ static bool_t thread_put(kobject_t *kobj);
static void thread_release_stage1(kobject_t *kobj);
static void thread_release_stage2(kobject_t *kobj);
typedef struct thread_wait_entry
{
slist_head_t node;
slist_head_t node_timeout;
thread_t *th;
mword_t times;
} thread_wait_entry_t;
static inline void thread_wait_entry_init(thread_wait_entry_t *entry, thread_t *th, mword_t times)
{
slist_init(&entry->node);
slist_init(&entry->node_timeout);
entry->th = th;
entry->times = times;
}
static slist_head_t wait_send_queue;
static slist_head_t wait_recv_queue;
@@ -66,8 +82,8 @@ void thread_init(thread_t *th, ram_limit_t *lim)
{
kobject_init(&th->kobj, THREAD_TYPE);
sched_init(&th->sche);
slist_init(&th->wait_node);
slist_init(&th->futex_node);
slist_init(&th->wait_send_head);
ref_counter_init(&th->ref);
ref_counter_inc(&th->ref);
th->lim = lim;
@@ -104,34 +120,37 @@ static void thread_release_stage1(kobject_t *kobj)
thread_suspend(th);
}
}
thread_t *pos;
thread_wait_entry_t *pos;
slist_foreach_not_next(pos, &wait_send_queue, wait_node)
slist_foreach_not_next(pos, &wait_send_queue, node_timeout)
{
assert(pos->status == THREAD_SUSPEND);
thread_t *next = slist_next_entry(pos, &th->wait_head, wait_node);
assert(pos->th->status == THREAD_SUSPEND);
thread_wait_entry_t *next = slist_next_entry(pos, &wait_send_queue, node_timeout);
pos->ipc_status = THREAD_IPC_ABORT;
thread_ready(pos, TRUE);
pos->th->ipc_status = THREAD_IPC_ABORT;
thread_ready(pos->th, TRUE);
slist_del(&pos->wait_node);
slist_del(&pos->node_timeout);
if (slist_in_list(&pos->node))
{
slist_del(&pos->node);
}
pos = next;
}
slist_foreach_not_next(pos, &wait_recv_queue, wait_node)
{
assert(pos->status == THREAD_SUSPEND);
thread_t *next = slist_next_entry(pos, &th->wait_head, wait_node);
thread_wait_entry_t *pos2;
pos->ipc_status = THREAD_IPC_ABORT;
thread_ready(pos, TRUE);
slist_del(&pos->wait_node);
pos = next;
}
if (slist_in_list(&th->wait_node))
slist_foreach_not_next(pos2, &wait_recv_queue, node)
{
slist_del(&th->wait_node); //!< 从链表中删除
assert(pos2->th->status == THREAD_SUSPEND);
thread_wait_entry_t *next = slist_next_entry(pos2, &wait_recv_queue, node);
pos2->th->ipc_status = THREAD_IPC_ABORT;
thread_ready(pos2->th, TRUE);
slist_del(&pos2->node);
pos2 = next;
}
thread_unbind(th);
}
static void thread_release_stage2(kobject_t *kobj)
@@ -301,45 +320,47 @@ thread_t *thread_create(ram_limit_t *ram)
*/
void thread_timeout_check(ssize_t tick)
{
thread_t *pos;
// thread_t *th = thread_get_current();
thread_wait_entry_t *pos;
slist_foreach_not_next(pos, &wait_send_queue, wait_node)
slist_foreach_not_next(pos, &wait_send_queue, node_timeout)
{
assert(pos->status == THREAD_SUSPEND);
thread_t *next = slist_next_entry(pos, &wait_send_queue, wait_node);
if (pos->ipc_times > 0)
assert(pos->th->status == THREAD_SUSPEND);
thread_wait_entry_t *next = slist_next_entry(pos, &wait_send_queue, node_timeout);
if (pos->times > 0)
{
pos->ipc_times -= tick;
if (pos->ipc_times <= 0)
pos->times -= tick;
if (pos->times <= 0)
{
pos->ipc_status = THREAD_TIMEOUT;
thread_ready(pos, TRUE);
pos->th->ipc_status = THREAD_TIMEOUT;
thread_ready(pos->th, TRUE);
slist_del(&pos->wait_node);
slist_del(&pos->node_timeout);
if (slist_in_list(&pos->node))
{
slist_del(&pos->node);
}
}
}
pos = next;
}
slist_foreach_not_next(pos, &wait_recv_queue, wait_node)
thread_wait_entry_t *pos2;
slist_foreach_not_next(pos2, &wait_recv_queue, node)
{
assert(pos->status == THREAD_SUSPEND);
thread_t *next = slist_next_entry(pos, &wait_recv_queue, wait_node);
assert(pos2->th->status == THREAD_SUSPEND);
thread_wait_entry_t *next = slist_next_entry(pos2, &wait_recv_queue, node);
if (pos->ipc_times > 0)
if (pos2->times > 0)
{
pos->ipc_times -= tick;
if (pos->ipc_times <= 0)
pos2->times -= tick;
if (pos2->times <= 0)
{
pos->ipc_status = THREAD_TIMEOUT;
thread_ready(pos, TRUE);
pos2->th->ipc_status = THREAD_TIMEOUT;
thread_ready(pos2->th, TRUE);
slist_del(&pos->wait_node);
slist_del(&pos2->node);
}
}
pos = next;
pos2 = next;
}
}
/**
@@ -411,22 +432,28 @@ static int thread_ipc_recv(msg_tag_t *ret_msg, ipc_timeout_t timeout, umword_t *
lock_status = cpulock_lock();
cur_th->ipc_status = THREAD_RECV; //!< 因为接收挂起
if (!slist_is_empty(&wait_send_queue))
if (!slist_is_empty(&cur_th->wait_send_head))
{
//!< 有发送者
slist_head_t *mslist = slist_first(&wait_send_queue);
thread_t *send_th = container_of(mslist, thread_t, wait_node);
slist_head_t *mslist = slist_first(&cur_th->wait_send_head);
thread_wait_entry_t *wait = container_of(mslist, thread_wait_entry_t, node);
slist_del(mslist); //!< 删除唤醒的线程
thread_ready(send_th, TRUE);
if (slist_in_list(&wait->node_timeout))
{
slist_del(&wait->node_timeout);
}
thread_ready(wait->th, TRUE);
}
else
{
//!< 加入等待队列
if (timeout.recv_timeout)
{
cur_th->ipc_times = timeout.recv_timeout;
slist_add_append(&wait_recv_queue, &cur_th->wait_node); //!< 放到等待队列中
thread_wait_entry_t wait;
thread_wait_entry_init(&wait, cur_th, timeout.recv_timeout);
slist_add_append(&wait_recv_queue, &wait.node); //!< 放到等待队列中
}
}
thread_suspend(cur_th); //!< 挂起
@@ -505,11 +532,15 @@ static int thread_ipc_send(thread_t *to_th, msg_tag_t in_tag, ipc_timeout_t timo
again_check:
if (recv_kobj->status == THREAD_READY)
{
thread_wait_entry_t wait;
cur_th->ipc_status = THREAD_SEND; //!< 因为发送挂起
cur_th->ipc_times = timout.send_timeout;
thread_suspend(cur_th); //!< 挂起
slist_add_append(&wait_send_queue, &cur_th->wait_node); //!< 放到等待队列中
preemption(); //!< 进行调度
thread_wait_entry_init(&wait, cur_th, timout.send_timeout);
slist_add_append(&recv_kobj->wait_send_head, &wait.node); //!< 放到线程的等待队列中
slist_add_append(&wait_send_queue, &wait.node_timeout);
thread_suspend(cur_th); //!< 挂起
preemption(); //!< 进行调度
if (cur_th->ipc_status == THREAD_IPC_ABORT)
{
cur_th->ipc_status = THREAD_NONE;
@@ -526,11 +557,11 @@ again_check:
}
else if (recv_kobj->status == THREAD_SUSPEND && recv_kobj->ipc_status == THREAD_RECV)
{
if (slist_in_list(&recv_kobj->wait_node))
{
//!< 如果已经在队列中,则删除
slist_del(&recv_kobj->wait_node);
}
// if (slist_in_list(&recv_kobj->wait_node))
// {
// //!< 如果已经在队列中,则删除
// slist_del(&recv_kobj->wait_node);
// }
//!< 开始发送数据
ret = ipc_data_copy(recv_kobj, cur_th, in_tag); //!< 拷贝数据
if (ret < 0)
@@ -563,11 +594,15 @@ static int thread_ipc_call(thread_t *to_th, msg_tag_t in_tag, msg_tag_t *ret_tag
again_check:
if (recv_kobj->status == THREAD_READY)
{
thread_wait_entry_t wait;
cur_th->ipc_status = THREAD_SEND; //!< 因为发送挂起
cur_th->ipc_times = timout.send_timeout;
thread_suspend(cur_th); //!< 挂起
slist_add_append(&wait_send_queue, &cur_th->wait_node); //!< 放到等待队列中
preemption(); //!< 进行调度
thread_wait_entry_init(&wait, cur_th, timout.send_timeout);
slist_add_append(&recv_kobj->wait_send_head, &wait.node); //!< 放到线程的等待队列中
slist_add_append(&wait_send_queue, &wait.node_timeout);
thread_suspend(cur_th); //!< 挂起
preemption();
if (cur_th->ipc_status == THREAD_IPC_ABORT)
{
cur_th->ipc_status = THREAD_NONE;
@@ -584,11 +619,11 @@ again_check:
}
else if (recv_kobj->status == THREAD_SUSPEND && recv_kobj->ipc_status == THREAD_RECV)
{
if (slist_in_list(&recv_kobj->wait_node))
{
//!< 如果已经在队列中,则删除
slist_del(&recv_kobj->wait_node);
}
// if (slist_in_list(&recv_kobj->wait_node))
// {
// //!< 如果已经在队列中,则删除
// slist_del(&recv_kobj->wait_node);
// }
//!< 开始发送数据
ret = ipc_data_copy(recv_kobj, cur_th, in_tag); //!< 拷贝数据
if (ret < 0)
@@ -747,8 +782,8 @@ static void thread_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_t
break;
case BIND_TASK:
{
kobject_t *task_kobj = obj_space_lookup_kobj(&task->obj_space, f->r[1]);
if (task_kobj == NULL /*TODO:检测kobj类型*/)
kobject_t *task_kobj = obj_space_lookup_kobj_cmp_type(&task->obj_space, f->r[1], TASK_TYPE);
if (task_kobj == NULL)
{
f->r[0] = msg_tag_init4(0, 0, 0, -ENOENT).raw;
return;

View File

@@ -1,9 +1,9 @@
#!/bin/bash
# export TOOLCHAIN=/home/zhangzheng/gcc-arm-none-eabi-5_4-2016q3/bin/
# export TOOLCHAIN_LIB=/home/zhangzheng/gcc-arm-none-eabi-5_4-2016q3/lib/gcc/arm-none-eabi/5.4.1/armv7-m
export TOOLCHAIN=/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/bin/
export TOOLCHAIN_LIB=/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/lib/gcc/arm-none-eabi/10.3.1/thumb/v7-m/nofp
export TOOLCHAIN=/home/zhangzheng/gcc-arm-none-eabi-5_4-2016q3/bin/
export TOOLCHAIN_LIB=/home/zhangzheng/gcc-arm-none-eabi-5_4-2016q3/lib/gcc/arm-none-eabi/5.4.1/armv7-m
# export TOOLCHAIN=/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/bin/
# export TOOLCHAIN_LIB=/Users/zhangzheng/gcc-arm-none-eabi-10.3-2021.10/lib/gcc/arm-none-eabi/10.3.1/thumb/v7-m/nofp
export KEN_OFFSET=0x2000
export INIT_OFFSET=0x10000
export BOOTFS_ADDR_OFFSET=0x20000