315 lines
6.7 KiB
C
Executable File
315 lines
6.7 KiB
C
Executable File
/**
|
|
* @file thread.c
|
|
* @author zhangzheng (1358745329@qq.com)
|
|
* @brief
|
|
* @version 0.1
|
|
* @date 2023-09-29
|
|
*
|
|
* @copyright Copyright (c) 2023
|
|
*
|
|
*/
|
|
|
|
#include "types.h"
|
|
#include "kobject.h"
|
|
#include "ram_limit.h"
|
|
#include "factory.h"
|
|
#include "thread.h"
|
|
#include "mm_wrap.h"
|
|
#include "string.h"
|
|
#include "init.h"
|
|
#include "task.h"
|
|
#include "thread.h"
|
|
#include "slist.h"
|
|
#include "thread_armv7m.h"
|
|
#include "assert.h"
|
|
#include "err.h"
|
|
static void thread_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag, entry_frame_t *f);
|
|
static bool_t thread_put(kobject_t *kobj);
|
|
static void thread_release_stage1(kobject_t *kobj);
|
|
static void thread_release_stage2(kobject_t *kobj);
|
|
/**
|
|
* @brief 线程的初始化函数
|
|
*
|
|
* @param th
|
|
*/
|
|
void thread_init(thread_t *th, ram_limit_t *lim)
|
|
{
|
|
kobject_init(&th->kobj);
|
|
sched_init(&th->sche);
|
|
// slist_init(&th->wait);
|
|
ref_counter_init(&th->ref);
|
|
ref_counter_inc(&th->ref);
|
|
th->lim = lim;
|
|
th->kobj.invoke_func = thread_syscall;
|
|
th->kobj.put_func = thread_put;
|
|
th->kobj.stage_1_func = thread_release_stage1;
|
|
th->kobj.stage_2_func = thread_release_stage2;
|
|
th->magic = THREAD_MAIGC;
|
|
}
|
|
static bool_t thread_put(kobject_t *kobj)
|
|
{
|
|
thread_t *th = container_of(kobj, thread_t, kobj);
|
|
|
|
return ref_counter_dec(&th->ref) == 1;
|
|
}
|
|
static void thread_release_stage1(kobject_t *kobj)
|
|
{
|
|
thread_t *th = container_of(kobj, thread_t, kobj);
|
|
kobject_invalidate(kobj);
|
|
thread_unbind(th);
|
|
if (th->status == THREAD_READY)
|
|
{
|
|
thread_suspend(th);
|
|
}
|
|
}
|
|
static void thread_release_stage2(kobject_t *kobj)
|
|
{
|
|
thread_t *th = container_of(kobj, thread_t, kobj);
|
|
thread_t *cur_th = thread_get_current();
|
|
|
|
printk("thread 0x%x\n", kobj);
|
|
mm_limit_free_align(th->lim, kobj, THREAD_BLOCK_SIZE);
|
|
|
|
if (cur_th == th)
|
|
{
|
|
thread_sched();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 设置运行寄存器
|
|
*
|
|
* @param th
|
|
* @param pc
|
|
* @param ip
|
|
*/
|
|
void thread_set_exc_regs(thread_t *th, umword_t pc, umword_t user_sp, umword_t ram, umword_t stack)
|
|
{
|
|
thread_user_pf_set(th, (void *)pc, (void *)user_sp, (void *)ram, stack);
|
|
}
|
|
/**
|
|
* @brief 线程绑定到task
|
|
*
|
|
* @param th
|
|
* @param tk
|
|
*/
|
|
void thread_bind(thread_t *th, kobject_t *tk)
|
|
{
|
|
th->task = tk;
|
|
task_t *tsk = container_of(tk, task_t, kobj);
|
|
|
|
ref_counter_inc(&tsk->ref_cn);
|
|
}
|
|
/**
|
|
* @brief 解除task绑定
|
|
*
|
|
* @param th
|
|
*/
|
|
void thread_unbind(thread_t *th)
|
|
{
|
|
if (th->task)
|
|
{
|
|
task_t *tsk = container_of(th->task, task_t, kobj);
|
|
|
|
ref_counter_dec_and_release(&tsk->ref_cn, &th->kobj);
|
|
th->task = NULL;
|
|
}
|
|
}
|
|
/**
|
|
* @brief 挂起一个线程
|
|
*
|
|
* @param th
|
|
*/
|
|
void thread_suspend(thread_t *th)
|
|
{
|
|
if (!slist_in_list(&th->sche.node))
|
|
{
|
|
assert(slist_in_list(&th->sche.node));
|
|
}
|
|
scheduler_del(&th->sche);
|
|
th->status = THREAD_SUSPEND;
|
|
thread_sched();
|
|
}
|
|
|
|
/**
|
|
* @brief 进行一次调度
|
|
*
|
|
* @param th
|
|
*/
|
|
void thread_sched(void)
|
|
{
|
|
sched_t *next_sche = scheduler_next();
|
|
thread_t *th = thread_get_current();
|
|
|
|
assert(th->magic == THREAD_MAIGC);
|
|
if (next_sche == &th->sche)
|
|
{
|
|
return;
|
|
}
|
|
to_sche();
|
|
}
|
|
/**
|
|
* @brief 线程进入就绪态
|
|
*
|
|
* @param th
|
|
*/
|
|
void thread_ready(thread_t *th, bool_t is_sche)
|
|
{
|
|
// if (!!slist_in_list(&th->sche.node))
|
|
// {
|
|
assert(!slist_in_list(&th->sche.node));
|
|
// }
|
|
scheduler_add(&th->sche);
|
|
th->status = THREAD_READY;
|
|
if (is_sche)
|
|
{
|
|
thread_sched();
|
|
}
|
|
}
|
|
/**
|
|
* @brief 创建线程
|
|
*
|
|
* @param ram
|
|
* @return thread_t*
|
|
*/
|
|
thread_t *thread_create(ram_limit_t *ram)
|
|
{
|
|
thread_t *th = mm_limit_alloc_align(ram, THREAD_BLOCK_SIZE, THREAD_BLOCK_SIZE);
|
|
|
|
if (!th)
|
|
{
|
|
return NULL;
|
|
}
|
|
memset(th, 0, THREAD_BLOCK_SIZE);
|
|
thread_init(th, ram);
|
|
return th;
|
|
}
|
|
enum thread_op
|
|
{
|
|
SET_EXEC_REGS,
|
|
RUN_THREAD,
|
|
BIND_TASK,
|
|
MSG_BUG_GET,
|
|
MSG_BUG_SET,
|
|
};
|
|
static void thread_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag, entry_frame_t *f)
|
|
{
|
|
msg_tag_t tag = msg_tag_init4(0, 0, 0, -EINVAL);
|
|
task_t *task = thread_get_current_task();
|
|
thread_t *tag_th = container_of(kobj, thread_t, kobj);
|
|
thread_t *cur_th = thread_get_current();
|
|
|
|
if (sys_p.prot != THREAD_PROT)
|
|
{
|
|
f->r[0] = msg_tag_init4(0, 0, 0, -EPROTO).raw;
|
|
return;
|
|
}
|
|
|
|
switch (sys_p.op)
|
|
{
|
|
case SET_EXEC_REGS:
|
|
{
|
|
umword_t stack_bottom = 0;
|
|
|
|
if (f->r[4]) //!< cp_stack
|
|
{
|
|
stack_bottom = (umword_t)(cur_th->msg.msg);
|
|
}
|
|
thread_set_exc_regs(tag_th, f->r[1], f->r[2], f->r[3], stack_bottom);
|
|
tag = msg_tag_init4(0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case MSG_BUG_SET:
|
|
{
|
|
/*TODO:检查内存的可访问性*/
|
|
thread_set_msg_bug(tag_th, (void *)(f->r[1]));
|
|
tag = msg_tag_init4(0, 0, 0, 0);
|
|
}
|
|
case MSG_BUG_GET:
|
|
{
|
|
f->r[1] = (umword_t)(tag_th->msg.msg);
|
|
f->r[2] = THREAD_MSG_BUG_LEN;
|
|
if (tag_th->msg.msg == NULL)
|
|
{
|
|
tag = msg_tag_init4(0, 0, 0, -EACCES);
|
|
}
|
|
else
|
|
{
|
|
tag = msg_tag_init4(0, 0, 0, 0);
|
|
}
|
|
}
|
|
break;
|
|
case RUN_THREAD:
|
|
{
|
|
if (!slist_in_list(&tag_th->sche.node))
|
|
{
|
|
tag_th->sche.prio = (f->r[1] >= PRIO_MAX ? PRIO_MAX - 1 : f->r[1]);
|
|
thread_ready(tag_th, TRUE);
|
|
}
|
|
tag = msg_tag_init4(0, 0, 0, 0);
|
|
}
|
|
break;
|
|
case BIND_TASK:
|
|
{
|
|
kobject_t *task_kobj = obj_space_lookup_kobj(&task->obj_space, f->r[1]);
|
|
if (task_kobj == NULL /*TODO:检测kobj类型*/)
|
|
{
|
|
f->r[0] = msg_tag_init4(0, 0, 0, -ENOENT).raw;
|
|
return;
|
|
}
|
|
thread_bind(tag_th, task_kobj);
|
|
tag = msg_tag_init4(0, 0, 0, 0);
|
|
printk("thread bind to %d\n", f->r[7], f->r[1]);
|
|
}
|
|
break;
|
|
}
|
|
f->r[0] = tag.raw;
|
|
}
|
|
|
|
/**
|
|
* @brief 该函数创建一个工厂对象
|
|
*
|
|
* @param lim
|
|
* @param arg0
|
|
* @param arg1
|
|
* @param arg2
|
|
* @param arg3
|
|
* @return kobject_t*
|
|
*/
|
|
static kobject_t *thread_create_func(ram_limit_t *lim, umword_t arg0, umword_t arg1,
|
|
umword_t arg2, umword_t arg3)
|
|
{
|
|
kobject_t *kobj = (kobject_t *)thread_create(lim);
|
|
if (!kobj)
|
|
{
|
|
return NULL;
|
|
}
|
|
printk("thread 0x%x\n", kobj);
|
|
return kobj;
|
|
}
|
|
|
|
/**
|
|
* @brief 工厂注册函数
|
|
*
|
|
*/
|
|
void thread_factory_register(void)
|
|
{
|
|
factory_register(thread_create_func, THREAD_PROT);
|
|
}
|
|
INIT_KOBJ(thread_factory_register);
|
|
/**
|
|
* @brief 获取当前的task
|
|
*
|
|
* @return task_t*
|
|
*/
|
|
task_t *thread_get_current_task(void)
|
|
{
|
|
return container_of(
|
|
thread_get_current()->task, task_t, kobj);
|
|
}
|
|
task_t *thread_get_task(thread_t *th)
|
|
{
|
|
return container_of(
|
|
th->task, task_t, kobj);
|
|
}
|