增加共享内存对象的支持
This commit is contained in:
@@ -98,7 +98,7 @@ static bool_t mpu_calc(
|
||||
|
||||
*ret_align_size = sub_region_t;
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
printk("st:0x%x re:0x%x sub:0x%x\n region:[", region[0]->block_start_addr, region[0]->region, sub_region_t);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
@@ -128,12 +128,6 @@ static bool_t mpu_calc(
|
||||
#endif
|
||||
mpu_calc_regs(region[0], region[0]->block_start_addr, ffs_t_, REGION_RWX, region[0]->region);
|
||||
mpu_calc_regs(region[1], region[1]->block_start_addr, ffs_t_, REGION_RWX, region[1]->region);
|
||||
// region_i[2].rbar = ARM_MPU_RBAR(2, 0x20010000/*TODO:*/);
|
||||
// region_i[2].rasr = ARM_MPU_RASR(0UL, ARM_MPU_AP_URO, 0UL
|
||||
// , 0UL, 1UL, 1UL, 0x0/*TODO:*/, 16-1/*TODO:*/);
|
||||
|
||||
// region_i[2].rbar = ARM_MPU_RBAR(2, 0x8000000 /*TODO:*/);
|
||||
// region_i[2].rasr = ARM_MPU_RASR(0UL, ARM_MPU_AP_URO, 0UL, 0UL, 1UL, 1UL, 0x0 /*TODO:*/, ffs(1024 * 1024) - 1 /*TODO:*/);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -250,10 +250,10 @@ int mem_heap_add(mem_t *_this, void *mem, uint32_t size)
|
||||
mem = (void *)(ALIGN((ptr_t)mem, 4));
|
||||
size -= 4;
|
||||
|
||||
((struct mem_heap *)mem)->name[0] = ' ';
|
||||
((struct mem_heap *)mem)->name[1] = ' ';
|
||||
((struct mem_heap *)mem)->name[2] = ' ';
|
||||
((struct mem_heap *)mem)->name[3] = ' ';
|
||||
// ((struct mem_heap *)mem)->name[0] = ' ';
|
||||
// ((struct mem_heap *)mem)->name[1] = ' ';
|
||||
// ((struct mem_heap *)mem)->name[2] = ' ';
|
||||
// ((struct mem_heap *)mem)->name[3] = ' ';
|
||||
((struct mem_heap *)mem)->used = 0;
|
||||
umword_t status = spinlock_lock(&_this->lock);
|
||||
if (!_this->heap_start)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* @file mm_space.c
|
||||
* @author ATShining (1358745329@qq.com)
|
||||
* @brief
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2023-09-29
|
||||
*
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*
|
||||
*/
|
||||
#include "types.h"
|
||||
#include "util.h"
|
||||
@@ -31,7 +31,7 @@ void mm_space_init(mm_space_t *mm_space, int is_knl)
|
||||
}
|
||||
region_info_t *mm_space_alloc_pt_region(mm_space_t *m_space)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (int i = 0; i < CONFIG_REGION_NUM; i++)
|
||||
{
|
||||
/*TODO:原子操作*/
|
||||
if (m_space->pt_regions[i].region_inx < 0)
|
||||
@@ -58,10 +58,27 @@ bool_t mm_space_add(mm_space_t *m_space,
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!is_power_of_2(size) || (addr & (!(size - 1))) != 0)
|
||||
{
|
||||
//!< 申请的大小必须是2的整数倍,而且地址也必须是2的整数倍
|
||||
mm_space_free_pt_region(m_space, ri);
|
||||
return FALSE;
|
||||
}
|
||||
mpu_calc_regs(ri, addr, ffs(size), attrs, 0);
|
||||
ri->start_addr = addr;
|
||||
ri->size = size;
|
||||
return TRUE;
|
||||
}
|
||||
void mm_space_del(mm_space_t *m_space)
|
||||
void mm_space_del(mm_space_t *m_space, umword_t addr)
|
||||
{
|
||||
/*TODO:*/
|
||||
for (int i = 0; i < CONFIG_REGION_NUM; i++)
|
||||
{
|
||||
if (m_space->pt_regions[i].region_inx >= 0 &&
|
||||
m_space->pt_regions[i].start_addr == addr)
|
||||
{
|
||||
m_space->pt_regions[i].region_inx = -1;
|
||||
m_space->pt_regions[i].start_addr = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* @file ram_limit.c
|
||||
* @author ATShining (1358745329@qq.com)
|
||||
* @brief
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2023-09-29
|
||||
*
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*
|
||||
*/
|
||||
#include "ram_limit.h"
|
||||
#include "types.h"
|
||||
@@ -25,7 +25,7 @@ bool_t ram_limit_alloc(ram_limit_t *limit, size_t size)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
limit->cur += size;
|
||||
limit->cur += size; // TODO:原子操作
|
||||
return TRUE;
|
||||
}
|
||||
void ram_limit_free(ram_limit_t *limit, size_t size)
|
||||
|
||||
291
mkrtos_knl/knl/share_mem.c
Normal file
291
mkrtos_knl/knl/share_mem.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/**
|
||||
* @file share_mem.c
|
||||
* @author zhangzheng (1358745329@qq.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2023-12-31
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
#include <types.h>
|
||||
#include <kobject.h>
|
||||
#include <task.h>
|
||||
#include <thread.h>
|
||||
#include <factory.h>
|
||||
#include "mm_wrap.h"
|
||||
#include "mpu.h"
|
||||
#include "init.h"
|
||||
#include "dlist.h"
|
||||
|
||||
/**
|
||||
* @brief 存储task的节点
|
||||
*
|
||||
*/
|
||||
typedef struct share_mem_task_node
|
||||
{
|
||||
dlist_item_t node;
|
||||
task_t *task;
|
||||
} share_mem_task_node_t;
|
||||
/**
|
||||
* @brief 共享内存对象
|
||||
*
|
||||
*/
|
||||
typedef struct share_mem
|
||||
{
|
||||
kobject_t kobj; //!< 内核对象
|
||||
void *mem; //!< 内存指针
|
||||
size_t size; //!< 内存大小,为n^2。
|
||||
dlist_head_t task_head; //!< 哪些任务使用了该共享内存
|
||||
ram_limit_t *lim; //!< 内存限额
|
||||
} share_mem_t;
|
||||
|
||||
enum share_mem_op
|
||||
{
|
||||
SHARE_MEM_MAP,
|
||||
SHARE_MEM_UNMAP,
|
||||
};
|
||||
/**
|
||||
* @brief 共享内存解除映射
|
||||
*
|
||||
* @param sm
|
||||
* @return int
|
||||
*/
|
||||
static void share_mem_unmap_task(share_mem_t *sm)
|
||||
{
|
||||
share_mem_task_node_t *pos;
|
||||
umword_t status = spinlock_lock(&sm->kobj.lock);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
task_t *tk = thread_get_current_task();
|
||||
dlist_foreach(&sm->task_head, pos, share_mem_task_node_t, node)
|
||||
{
|
||||
if (pos->task == tk)
|
||||
{
|
||||
dlist_del(&sm->task_head, &pos->node);
|
||||
mm_limit_free(tk->lim, pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spinlock_set(&sm->kobj.lock, status);
|
||||
}
|
||||
/**
|
||||
* @brief 共享内存映射
|
||||
*
|
||||
* @param task
|
||||
*/
|
||||
static int share_mem_map_task(share_mem_t *sm)
|
||||
{
|
||||
int ret = -1;
|
||||
int flag = 0;
|
||||
share_mem_task_node_t *pos;
|
||||
umword_t status = spinlock_lock(&sm->kobj.lock);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
task_t *tk = thread_get_current_task();
|
||||
|
||||
dlist_foreach(&sm->task_head, pos, share_mem_task_node_t, node)
|
||||
{
|
||||
if (pos->task == tk)
|
||||
{
|
||||
flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag)
|
||||
{
|
||||
// 没有找到则插入一个新的
|
||||
share_mem_task_node_t *task_node = mm_limit_alloc(tk->lim, sizeof(share_mem_task_node_t));
|
||||
|
||||
if (!task_node)
|
||||
{
|
||||
// 内存分配失败
|
||||
ref_counter_dec_and_release(&tk->ref_cn, &tk->kobj);
|
||||
spinlock_set(&sm->kobj.lock, status);
|
||||
ret = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
dlist_item_init(&task_node->node);
|
||||
task_node->task = tk;
|
||||
dlist_add_head(&sm->task_head, &task_node->node);
|
||||
ref_counter_inc(&tk->ref_cn);
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
end:
|
||||
spinlock_set(&sm->kobj.lock, status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void share_mem_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();
|
||||
share_mem_t *sm = container_of(kobj, share_mem_t, kobj);
|
||||
|
||||
if (sys_p.prot != SHARE_MEM_PROT)
|
||||
{
|
||||
f->r[0] = msg_tag_init4(0, 0, 0, -EPROTO).raw;
|
||||
return;
|
||||
}
|
||||
switch (sys_p.op)
|
||||
{
|
||||
case SHARE_MEM_MAP:
|
||||
{
|
||||
uint8_t attr;
|
||||
|
||||
attr = f->r[0] & 0xff;
|
||||
int map_ret = share_mem_map_task(sm);
|
||||
|
||||
if (map_ret >= 0)
|
||||
{
|
||||
if (map_ret == 0)
|
||||
{
|
||||
// 共享内存映射
|
||||
bool_t ret = mm_space_add(&task->mm_space, (umword_t)(sm->mem), sm->size, attr);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
mpu_switch_to_task(task);
|
||||
}
|
||||
else
|
||||
{
|
||||
share_mem_unmap_task(sm);
|
||||
map_ret == -EAGAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
f->r[1] = (umword_t)sm->mem;
|
||||
f->r[2] = sm->size;
|
||||
tag = msg_tag_init4(0, 0, 0, map_ret);
|
||||
}
|
||||
break;
|
||||
case SHARE_MEM_UNMAP:
|
||||
{
|
||||
// 从记录中删除
|
||||
share_mem_unmap_task(sm);
|
||||
// 共享内存解除映射
|
||||
mm_space_del(&task->mm_space, (umword_t)sm->mem);
|
||||
mpu_switch_to_task(task);
|
||||
ref_counter_dec_and_release(&task->ref_cn, &task->kobj);
|
||||
tag = msg_tag_init4(0, 0, 0, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
f->r[0] = tag.raw;
|
||||
}
|
||||
static void share_mem_unmap(obj_space_t *obj_space, kobject_t *kobj)
|
||||
{
|
||||
task_t *task = container_of(obj_space, task_t, obj_space);
|
||||
share_mem_t *sm = container_of(kobj, share_mem_t, kobj);
|
||||
|
||||
// 从记录中删除
|
||||
share_mem_unmap_task(sm);
|
||||
// 共享内存解除映射
|
||||
mm_space_del(&task->mm_space, (umword_t)sm->mem);
|
||||
mpu_switch_to_task(task);
|
||||
ref_counter_dec_and_release(&task->ref_cn, &task->kobj);
|
||||
}
|
||||
static void share_mem_release_stage1(kobject_t *kobj)
|
||||
{
|
||||
share_mem_t *sm = container_of(kobj, share_mem_t, kobj);
|
||||
kobject_invalidate(kobj);
|
||||
}
|
||||
static void share_mem_release_stage2(kobject_t *kobj)
|
||||
{
|
||||
share_mem_t *sm = container_of(kobj, share_mem_t, kobj);
|
||||
|
||||
assert(dlist_is_empty(&sm->task_head));
|
||||
|
||||
mm_limit_free_align(sm->lim, sm->mem, sm->size);
|
||||
mm_limit_free(sm->lim, sm);
|
||||
printk("share mem 0x%x free.\n", sm);
|
||||
}
|
||||
/**
|
||||
* @brief share_mem init.
|
||||
*
|
||||
* @param fac 初始化的share_mem对象
|
||||
* @param max 最大限额值
|
||||
*/
|
||||
static void share_mem_init(share_mem_t *sm, umword_t max)
|
||||
{
|
||||
kobject_init(&sm->kobj, SHARE_MEM_TYPE);
|
||||
sm->kobj.invoke_func = share_mem_syscall;
|
||||
sm->kobj.unmap_func = share_mem_unmap;
|
||||
sm->kobj.stage_1_func = share_mem_release_stage1;
|
||||
sm->kobj.stage_2_func = share_mem_release_stage2;
|
||||
}
|
||||
/**
|
||||
* @brief 创建共享内存对象
|
||||
*
|
||||
* @param lim
|
||||
* @param max
|
||||
* @return share_mem_t*
|
||||
*/
|
||||
static share_mem_t *share_mem_create(ram_limit_t *lim, size_t max)
|
||||
{
|
||||
|
||||
if (max < PAGE_SIZE || !is_power_of_2(max))
|
||||
{
|
||||
//!< 大小必须是2的整数倍
|
||||
return NULL;
|
||||
}
|
||||
|
||||
share_mem_t *mem = mm_limit_alloc(lim, sizeof(share_mem_t));
|
||||
|
||||
if (!mem)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
mem->mem = mm_limit_alloc_align(lim, max, max);
|
||||
if (!mem->mem)
|
||||
{
|
||||
mm_limit_free(lim, mem);
|
||||
return NULL;
|
||||
}
|
||||
mem->size = max;
|
||||
mem->lim = lim;
|
||||
share_mem_init(mem, max);
|
||||
return mem;
|
||||
}
|
||||
/**
|
||||
* @brief 共享内存对象创建的回调函数
|
||||
*
|
||||
* @param lim
|
||||
* @param arg0
|
||||
* @param arg1
|
||||
* @param arg2
|
||||
* @param arg3
|
||||
* @return kobject_t*
|
||||
*/
|
||||
static kobject_t *share_mem_func(ram_limit_t *lim, umword_t arg0, umword_t arg1,
|
||||
umword_t arg2, umword_t arg3)
|
||||
{
|
||||
share_mem_t *irq = share_mem_create(lim, arg0);
|
||||
|
||||
if (!irq)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &irq->kobj;
|
||||
}
|
||||
/**
|
||||
* @brief 工厂注册函数
|
||||
*
|
||||
*/
|
||||
static void share_mem_register(void)
|
||||
{
|
||||
factory_register(share_mem_func, SHARE_MEM_PROT);
|
||||
}
|
||||
INIT_KOBJ(share_mem_register);
|
||||
@@ -289,7 +289,7 @@ void task_init(task_t *task, ram_limit_t *ram, int is_knl)
|
||||
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.配置
|
||||
mm_space_add(&task->mm_space, CONFIG_KNL_TEXT_ADDR, CONFIG_KNL_TEXT_SIZE, REGION_RO); // TODO:这里应该用config.配置
|
||||
}
|
||||
|
||||
static bool_t task_put(kobject_t *kobj)
|
||||
|
||||
@@ -57,7 +57,6 @@ static void knl_main(void)
|
||||
task_t *next = slist_next_entry(pos, &del_task_head, del_node);
|
||||
slist_del(&pos->del_node);
|
||||
{
|
||||
// TODO:给init发送消息,该函数是在中断中调用的,所以这个消息只能在knl_thread中调用。
|
||||
msg_tag_t tag;
|
||||
umword_t user_id;
|
||||
ipc_msg_t *msg = (ipc_msg_t *)knl_msg_buf;
|
||||
@@ -65,7 +64,7 @@ static void knl_main(void)
|
||||
msg->msg_buf[1] = pos->pid;
|
||||
msg->msg_buf[2] = 0;
|
||||
int ret = thread_ipc_call(init_thread, msg_tag_init4(0, 3, 0, 0x0005 /*PM_PROT*/),
|
||||
&tag, ipc_timeout_create2(0, 0), &user_id);
|
||||
&tag, ipc_timeout_create2(3000, 3000), &user_id);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user