Files
mkrtos-real/mkrtos_knl/knl/task.c

372 lines
9.1 KiB
C
Raw Normal View History

2023-09-29 01:03:19 +08:00
/**
* @file task.c
* @author ATShining (1358745329@qq.com)
* @brief
2023-09-29 01:03:19 +08:00
* @version 0.1
* @date 2023-09-29
*
2023-09-29 01:03:19 +08:00
* @copyright Copyright (c) 2023
*
2023-09-29 01:03:19 +08:00
*/
2023-08-20 20:52:23 +08:00
#include "task.h"
#include "kobject.h"
#include "factory.h"
#include "init.h"
2023-08-28 22:11:49 +08:00
#include "map.h"
#include "thread.h"
#include "misc.h"
2023-09-02 00:18:54 +08:00
#include "spinlock.h"
2023-11-19 23:01:35 +08:00
#include "string.h"
/**
* @brief
*
*/
2023-08-20 20:52:23 +08:00
enum task_op_code
{
TASK_OBJ_MAP, //!< 进行映射操作
TASK_OBJ_UNMAP, //!< 进行解除映射操作
TASK_ALLOC_RAM_BASE, //!< 分配task的基础内存
TASK_OBJ_VALID, //!< 判断一个对象是否有效
TASK_SET_PID, //!< 设置task的pid
TASK_GET_PID, //!< 获取task的pid
2023-08-20 20:52:23 +08:00
};
2023-08-28 22:11:49 +08:00
static bool_t task_put(kobject_t *kobj);
static void task_release_stage1(kobject_t *kobj);
static void task_release_stage2(kobject_t *kobj);
/**
* @brief task分配其可以使用的内存空间
*
* @param tk
* @param lim
* @param size
* @return int
*/
int task_alloc_base_ram(task_t *tk, ram_limit_t *lim, size_t size)
{
if (tk->mm_space.mm_block)
{
return -EACCES;
}
// 申请init的ram内存
2023-09-03 15:55:06 +08:00
void *ram = mpu_ram_alloc(&tk->mm_space, lim, size + THREAD_MSG_BUG_LEN);
if (!ram)
{
printk("Failed to request process memory.\n");
return -ENOMEM;
}
2023-11-19 23:01:35 +08:00
memset(ram, 0, size + THREAD_MSG_BUG_LEN);
2023-09-03 15:55:06 +08:00
mm_space_set_ram_block(&tk->mm_space, ram, size + THREAD_MSG_BUG_LEN);
printk("task alloc size is %d, base is 0x%x\n", size + THREAD_MSG_BUG_LEN, ram);
return 0;
}
/**
* @brief 线task
*
* @param th
* @return task_t*
*/
2023-09-03 15:55:06 +08:00
task_t *thread_get_bind_task(thread_t *th)
{
return container_of(th->task, task_t, kobj);
}
/**
* @brief
*
* @param sp0
* @param sp1
* @param status0
* @param status1
*/
static void task_unlock_2(spinlock_t *sp0, spinlock_t *sp1, int status0, int status1)
{
if (sp0 < sp1)
{
spinlock_set(sp1, status1);
spinlock_set(sp0, status0);
}
else
{
spinlock_set(sp0, status0);
spinlock_set(sp1, status1);
}
}
/**
* @brief
*
* @param sp0
* @param sp1
* @param st0
* @param st1
* @return int
*/
static int task_lock_2(spinlock_t *sp0, spinlock_t *sp1, int *st0, int *st1)
{
int status0;
int status1;
if (sp0 < sp1)
{
status0 = spinlock_lock(sp0);
if (status0 < 0)
{
return FALSE;
}
status1 = spinlock_lock(sp1);
if (status1 < 0)
{
spinlock_set(sp0, status0);
return FALSE;
}
*st0 = status0;
*st1 = status1;
}
else
{
status0 = spinlock_lock(sp1);
if (status0 < 0)
{
return FALSE;
}
status1 = spinlock_lock(sp0);
if (status1 < 0)
{
spinlock_set(sp1, status0);
return FALSE;
}
*st0 = status1;
*st1 = status0;
}
return TRUE;
}
/**
* @brief pidpid为0的进程才能够设置
*
* @param task
* @param pid pid
* @return int
*/
2023-12-01 22:18:10 +08:00
int task_set_pid(task_t *task, pid_t pid)
{
task_t *cur_task = thread_get_current_task();
if (cur_task->pid == 0)
{
task->pid = pid;
return 0;
}
else
{
return -EACCES;
}
}
/**
* @brief
*
* @param kobj
* @param sys_p
* @param in_tag
* @param f
*/
2023-09-03 15:55:06 +08:00
static void task_syscall_func(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag, entry_frame_t *f)
2023-08-20 20:52:23 +08:00
{
2023-08-28 22:11:49 +08:00
task_t *cur_task = thread_get_current_task();
task_t *tag_task = container_of(kobj, task_t, kobj);
2023-09-07 23:47:34 +08:00
msg_tag_t tag = msg_tag_init4(0, 0, 0, -EINVAL);
2023-08-20 20:52:23 +08:00
2023-09-03 15:55:06 +08:00
if (sys_p.prot != TASK_PROT)
2023-08-20 20:52:23 +08:00
{
2023-09-07 23:47:34 +08:00
f->r[0] = msg_tag_init4(0, 0, 0, -EINVAL).raw;
2023-09-03 15:55:06 +08:00
return;
2023-08-20 20:52:23 +08:00
}
2023-09-03 15:55:06 +08:00
switch (sys_p.op)
2023-08-20 20:52:23 +08:00
{
case TASK_OBJ_VALID: //!< 查看某个obj在task中是否存在
2023-09-07 23:47:34 +08:00
{
mword_t status = spinlock_lock(&tag_task->kobj.lock);
if (status < 0)
{
tag = msg_tag_init4(0, 0, 0, -EINVAL);
break;
}
2023-09-07 23:47:34 +08:00
kobject_t *source_kobj = obj_space_lookup_kobj(&cur_task->obj_space, f->r[1]);
if (!source_kobj)
{
spinlock_set(&tag_task->kobj.lock, status);
2023-09-07 23:47:34 +08:00
tag = msg_tag_init4(0, 0, 0, -ENOENT);
break;
}
spinlock_set(&tag_task->kobj.lock, status);
2023-09-07 23:47:34 +08:00
tag = msg_tag_init4(0, 0, 0, 1);
}
break;
case TASK_OBJ_MAP://!<从一个task中映射一个对象到目标进程
{
2023-09-21 21:44:17 +08:00
kobj_del_list_t del;
int st0, st1;
2023-09-21 21:44:17 +08:00
kobj_del_list_init(&del);
int suc = task_lock_2(&tag_task->kobj.lock, &cur_task->kobj.lock, &st0, &st1);
if (!suc)
{
tag = msg_tag_init4(0, 0, 0, -EINVAL);
break;
}
2023-09-09 14:39:48 +08:00
int ret = obj_map_src_dst(&tag_task->obj_space, &cur_task->obj_space,
f->r[2], f->r[1],
2023-09-21 21:44:17 +08:00
tag_task->lim, f->r[3], &del);
kobj_del_list_to_do(&del);
task_unlock_2(&tag_task->kobj.lock, &cur_task->kobj.lock, st0, st1);
2023-09-07 23:47:34 +08:00
tag = msg_tag_init4(0, 0, 0, ret);
}
break;
case TASK_OBJ_UNMAP://!<解除task中一个进程的创建
2023-08-28 22:11:49 +08:00
{
kobject_t *del_kobj;
kobj_del_list_t kobj_list;
2023-09-02 00:18:54 +08:00
mword_t status = spinlock_lock(&tag_task->kobj.lock);
if (status < 0)
{
2023-09-07 23:47:34 +08:00
tag = msg_tag_init4(0, 0, 0, -EINVAL);
2023-09-02 00:18:54 +08:00
break;
}
2023-08-28 22:11:49 +08:00
kobj_del_list_init(&kobj_list);
2023-09-09 14:39:48 +08:00
obj_unmap(&tag_task->obj_space, vpage_create_raw(f->r[1]), &kobj_list);
2023-08-28 22:11:49 +08:00
kobj_del_list_to_do(&kobj_list);
2023-09-02 00:18:54 +08:00
spinlock_set(&tag_task->kobj.lock, status);
tag = msg_tag_init4(0, 0, 0, 0);
2023-08-28 22:11:49 +08:00
}
break;
case TASK_ALLOC_RAM_BASE://!< 分配task所拥有的内存空间
{
2023-09-02 00:18:54 +08:00
mword_t status = spinlock_lock(&tag_task->kobj.lock);
if (status < 0)
{
2023-09-07 23:47:34 +08:00
tag = msg_tag_init4(0, 0, 0, -EINVAL);
2023-09-02 00:18:54 +08:00
break;
}
int ret = task_alloc_base_ram(tag_task, tag_task->lim, f->r[1]);
2023-09-07 23:47:34 +08:00
tag = msg_tag_init4(0, 0, 0, ret);
2023-09-03 15:55:06 +08:00
f->r[1] = (umword_t)(tag_task->mm_space.mm_block);
2023-09-02 00:18:54 +08:00
spinlock_set(&tag_task->kobj.lock, status);
}
break;
case TASK_SET_PID://!<设置pid
2023-11-29 23:25:32 +08:00
{
2023-12-01 22:18:10 +08:00
tag = msg_tag_init4(0, 0, 0, task_set_pid(tag_task, f->r[0]));
2023-11-29 23:25:32 +08:00
}
break;
case TASK_GET_PID://!<获取pid
2023-11-29 23:25:32 +08:00
{
f->r[1] = tag_task->pid;
tag = msg_tag_init4(0, 0, 0, 0);
}
break;
2023-08-20 20:52:23 +08:00
default:
break;
}
2023-09-03 15:55:06 +08:00
f->r[0] = tag.raw;
2023-08-20 20:52:23 +08:00
}
2023-08-27 21:25:09 +08:00
void task_init(task_t *task, ram_limit_t *ram, int is_knl)
2023-08-20 20:52:23 +08:00
{
assert(task);
assert(ram);
kobject_init(&task->kobj, TASK_TYPE);
2023-08-20 20:52:23 +08:00
obj_space_init(&task->obj_space, ram);
2023-08-27 21:25:09 +08:00
mm_space_init(&task->mm_space, is_knl);
2023-08-28 22:11:49 +08:00
ref_counter_init(&task->ref_cn);
ref_counter_inc(&task->ref_cn);
slist_init(&task->del_node);
2023-12-02 09:49:15 +08:00
task->pid = -1;
2023-08-27 16:52:53 +08:00
task->lim = ram;
2023-08-28 22:11:49 +08:00
task->kobj.invoke_func = task_syscall_func;
task->kobj.put_func = task_put;
task->kobj.stage_1_func = task_release_stage1;
task->kobj.stage_2_func = task_release_stage2;
mm_space_add(&task->mm_space, CONFIG_KNL_TEXT_ADDR, 64 * 1024 * 1024, REGION_RO); // TODO:这里应该用config.配置
2023-08-28 22:11:49 +08:00
}
static bool_t task_put(kobject_t *kobj)
{
task_t *tk = container_of(kobj, task_t, kobj);
return ref_counter_dec(&tk->ref_cn) == 1;
}
static void task_release_stage1(kobject_t *kobj)
{
task_t *tk = container_of(kobj, task_t, kobj);
kobj_del_list_t kobj_list;
2023-09-02 00:18:54 +08:00
kobject_invalidate(kobj);
2023-08-28 22:11:49 +08:00
kobj_del_list_init(&kobj_list);
obj_unmap_all(&tk->obj_space, &kobj_list);
kobj_del_list_to_do(&kobj_list);
}
static void task_release_stage2(kobject_t *kobj)
{
task_t *tk = container_of(kobj, task_t, kobj);
kobj_del_list_t kobj_list;
2023-10-05 23:10:18 +08:00
// task_t *cur_tk = thread_get_current_task();
2023-08-28 22:11:49 +08:00
obj_space_release(&tk->obj_space, tk->lim);
mm_limit_free_align(tk->lim, tk->mm_space.mm_block, tk->mm_space.mm_block_size);
2023-08-28 22:11:49 +08:00
mm_limit_free(tk->lim, tk);
// if (cur_tk == tk)
// {
thread_sched();
// }
2023-10-01 01:56:55 +08:00
// mm_trace();
2023-08-28 22:11:49 +08:00
printk("release tk %x\n", tk);
2023-08-20 20:52:23 +08:00
}
void task_kill(task_t *tk)
{
kobj_del_list_t kobj_list;
kobj_del_list_init(&kobj_list);
obj_unmap(&tk->obj_space, vpage_create3(KOBJ_DELETE_RIGHT, 0, TASK_PROT), &kobj_list);
kobj_del_list_to_do(&kobj_list);
thread_sched();
}
2023-08-27 21:25:09 +08:00
task_t *task_create(ram_limit_t *lim, int is_knl)
2023-08-20 20:52:23 +08:00
{
task_t *tk = mm_limit_alloc(lim, sizeof(task_t));
if (!tk)
{
return NULL;
}
2023-08-27 21:25:09 +08:00
task_init(tk, lim, is_knl);
printk("create task is 0x%x\n", tk);
2023-08-20 20:52:23 +08:00
return tk;
}
/**
* @brief
*
* @param lim
* @param arg0
* @param arg1
* @param arg2
* @param arg3
* @return kobject_t*
*/
static kobject_t *task_create_func(ram_limit_t *lim, umword_t arg0, umword_t arg1,
umword_t arg2, umword_t arg3)
{
2023-08-27 21:25:09 +08:00
task_t *tk = task_create(lim, FALSE);
2023-08-20 20:52:23 +08:00
return &tk->kobj;
}
/**
* @brief TODO:
*
*/
2023-08-22 00:26:34 +08:00
void task_factory_register(void)
2023-08-20 20:52:23 +08:00
{
factory_register(task_create_func, TASK_PROT);
}
2023-08-22 00:26:34 +08:00
INIT_KOBJ(task_factory_register);