修复fipc并发通信时映射错错乱的问题

This commit is contained in:
zhangzheng
2025-03-31 00:23:35 +08:00
parent 1013936ec1
commit 2fef3f4889
45 changed files with 487 additions and 183 deletions

View File

@@ -8,7 +8,6 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
-Wno-builtin-declaration-mismatch \
")
# -O1 \
# -Ofast \
# message(编译参数:${CMAKE_C_FLAGS})

View File

@@ -34,7 +34,7 @@ typedef struct task
mutex_t nofity_lock;
sema_t notify_sema; //!< sema
addr_t nofity_msg_buf; //!<
umword_t *nofity_map_buf;
obj_handler_t (*nofity_map_buf)[CONFIG_THREAD_MAP_BUF_LEN];
umword_t *nofity_bitmap; //!<
int nofity_bitmap_len; //!< max is WORD_BITS
slist_head_t nofity_theads_head;
@@ -43,7 +43,16 @@ typedef struct task
size_t text_size;
pid_t pid; //!< task pid.
} task_t;
typedef struct
{
void *com_point_func;
addr_t stack;
umword_t stack_size;
void *bitmap;
int bitmap_len;
void *msg_buf;
obj_handler_t (*map_buf)[CONFIG_THREAD_MAP_BUF_LEN];
} fast_ipc_info_t;
static inline pid_t task_pid_get(task_t *task)
{
return task->pid;

View File

@@ -80,11 +80,13 @@ int u_ipc_bind(ipc_t *ipc, obj_handler_t tk_hd, umword_t user_id, task_t *tk_kob
if (!recv_kobj)
{
ret = -ENOENT;
goto end_bind;
spinlock_set(&cur_task->kobj.lock, status);
return ret;
}
ref_counter_inc(&recv_kobj->ref_cn); //!< 绑定后线程的引用计数+1防止被删除
ipc->svr_tk = recv_kobj;
ipc->user_id = user_id;
spinlock_set(&cur_task->kobj.lock, status);
// ipc_wait_bind_entry_t *pos;
// slist_foreach_not_next(pos, &ipc->wait_bind, node) //!< 唤醒所有等待绑定的线程
@@ -97,10 +99,6 @@ int u_ipc_bind(ipc_t *ipc, obj_handler_t tk_hd, umword_t user_id, task_t *tk_kob
// }
sema_up(&ipc->wait_bind);
ret = 0;
end_bind:
//!< 先解锁然后在给task的引用计数-1
spinlock_set(&cur_task->kobj.lock, status);
// ref_counter_dec_and_release(&cur_task->ref_cn, &cur_task->kobj);
}
else
{

View File

@@ -60,14 +60,14 @@ typedef struct share_mem
size_t size; //!< Memory size, (depending on arch, size may be limited to, for example: n^2
dlist_head_t task_head; //!< Which tasks use the shared memory
share_mem_type_t mem_type; //!< memory type
ram_limit_t *lim; //!< memory limit
ram_limit_t *lim; //!< memory limit
ref_counter_t ref; //!< Reference count must be zero to free kobj memory
} share_mem_t;
enum share_mem_op
{
SHARE_MEM_MAP, //!<share mem map to task.
SHARE_MEM_UNMAP, //!< share mem unmap to task.
SHARE_MEM_MAP, //!< share mem map to task.
SHARE_MEM_UNMAP, //!< share mem unmap to task.
SHARE_MEM_RESIZE, //!< share mem resize.
};
#if IS_ENABLED(CONFIG_BUDDY_SLAB)
@@ -379,7 +379,7 @@ static ssize_t share_mem_map(share_mem_t *obj, vma_addr_t addr, vaddr_t *ret_vad
#if IS_ENABLED(CONFIG_MMU)
vaddr_t ret_addr;
addr.flags |= VMA_ADDR_RESV;
addr.flags |= VMA_ADDR_RESV;
//!< Set to reserve memory, physical memory that reserves memory and does not apply for it in the kernel
ret = task_vma_alloc(&task->mm_space.mem_vma, addr, obj->size, 0, &ret_addr); //!< Apply for virtual memory
if (ret < 0)
@@ -428,8 +428,10 @@ static ssize_t share_mem_map(share_mem_t *obj, vma_addr_t addr, vaddr_t *ret_vad
(vaddr_t)(obj->mem), ret_vaddr);
if (ret < 0)
{
printk("share mem task map failed, pmem:0x%x vmem:0x%x.\n", obj->mem, *ret_vaddr);
return ret;
}
// printk("share mem task map, pmem:0x%x vmem:0x%x.\n", obj->mem, *ret_vaddr);
map_size = obj->size;
// *ret_vaddr = (vaddr_t)(obj->mem);
#endif
@@ -453,6 +455,7 @@ static void share_mem_unmap_op(task_t *tk, share_mem_t *sm)
share_mem_unmap(sm, addr);
ref_counter_dec_and_release(&tk->ref_cn, &tk->kobj);
ref_counter_dec_and_release(&sm->ref, &sm->kobj);
// printk("share mem task unmap, pmem:0x%x vmem:0x%x.\n", sm->mem, addr);
}
}
static void share_mem_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag, entry_frame_t *f)
@@ -523,7 +526,7 @@ static void share_mem_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t i
ret = share_mem_pmem_resize(sm, f->regs[0]);
}
spinlock_set(&sm->kobj.lock, status);
resize_end:
resize_end:
tag = msg_tag_init4(0, 0, 0, ret);
}
}

View File

@@ -436,36 +436,49 @@ static void task_syscall_func(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t i
break;
case TASK_SET_COM_POINT: //!< 设置通信点
{
if (!is_rw_access(tag_task, (void *)(f->regs[1]), f->regs[2], FALSE))
fast_ipc_info_t *fipc_info = (fast_ipc_info_t *)(f->regs[0]);
if (!is_rw_access(tag_task, (void *)(fipc_info), sizeof(*fipc_info), FALSE))
{
printk("%s:%d fipc_info is not rw access\n", __func__, __LINE__);
tag = msg_tag_init4(0, 0, 0, -EPERM);
break;
}
if (f->regs[4] >= WORD_BITS)
if (!is_rw_access(tag_task, (void *)(fipc_info->stack), fipc_info->stack_size, FALSE))
{
printk("%s:%d fipc_info is not rw access\n", __func__, __LINE__);
tag = msg_tag_init4(0, 0, 0, -EPERM);
break;
}
if (fipc_info->bitmap_len >= WORD_BITS)
{
printk("%s:%d fipc_info stack_len is to long\n", __func__, __LINE__);
tag = msg_tag_init4(0, 0, 0, -EINVAL);
break;
}
if (!is_rw_access(tag_task, (void *)(f->regs[3]),
ROUND_UP(f->regs[4], 8), FALSE))
if (!is_rw_access(tag_task, (void *)(fipc_info->bitmap),
ROUND_UP(fipc_info->bitmap_len, 8), FALSE))
{
printk("%s:%d fipc_info is not rw access\n", __func__, __LINE__);
tag = msg_tag_init4(0, 0, 0, -EPERM);
break;
}
if (!is_rw_access(tag_task, (void *)(f->regs[5]),
THREAD_MSG_BUG_LEN + CONFIG_THREAD_MAP_BUF_LEN * WORD_BYTES, FALSE))
if (!is_rw_access(tag_task, (void *)(fipc_info->msg_buf),
THREAD_MSG_BUG_LEN * fipc_info->bitmap_len, FALSE))
{
printk("%s:%d fipc_info is not rw access\n", __func__, __LINE__);
tag = msg_tag_init4(0, 0, 0, -EPERM);
break;
}
int stack_size = f->regs[2];
tag_task->notify_point = (void *)(f->regs[0]);
tag_task->nofity_stack = (addr_t)(f->regs[1] + stack_size);
tag_task->nofity_bitmap = (void *)(f->regs[3]);
tag_task->nofity_bitmap_len = (f->regs[4]);
tag_task->nofity_msg_buf = (addr_t)f->regs[5];
tag_task->nofity_map_buf = (umword_t *)((addr_t)f->regs[5] + THREAD_MSG_BUG_LEN);
tag_task->notify_point = (void *)(fipc_info->com_point_func);
tag_task->nofity_stack = (addr_t)(fipc_info->stack + fipc_info->stack_size);
tag_task->nofity_bitmap = (void *)(fipc_info->bitmap);
tag_task->nofity_bitmap_len = (fipc_info->bitmap_len);
tag_task->nofity_msg_buf = (addr_t)fipc_info->msg_buf;
tag_task->nofity_map_buf = fipc_info->map_buf;
sema_init(&tag_task->notify_sema, tag_task->nofity_bitmap_len, tag_task->nofity_bitmap_len);
tag = msg_tag_init4(0, 0, 0, 0);
}

View File

@@ -478,6 +478,22 @@ static int ipc_dat_copy_raw(obj_space_t *dst_obj, obj_space_t *src_obj, ram_limi
MIN(tag.msg_buf_len * WORD_BYTES, IPC_MSG_SIZE));
return i;
}
static inline int fipc_alloc_channle(task_t *tk)
{
for (int i = 0; i < tk->nofity_bitmap_len; i++)
{
if (((*tk->nofity_bitmap) & (0x1 << i)) == 0)
{
*tk->nofity_bitmap |= 0x1 << i;
return i;
}
}
return -1;
}
static inline void fipc_free_channle(task_t *tk, int inx)
{
*(tk->nofity_bitmap) &= ~(1 << MIN(inx, tk->nofity_bitmap_len)); //!< 解锁bitmap
}
/**
* 快速ipc call
* FIXME:以下代码是arch相关的需要整理
@@ -509,11 +525,16 @@ msg_tag_t thread_fast_ipc_call(task_t *to_task, entry_frame_t *f, umword_t user_
assert(cur_th->magic == THREAD_MAGIC);
ref_counter_inc((&to_task->ref_cn));
int fipc_channel;
fipc_channel = fipc_alloc_channle(to_task); //!< 分配一个通道
assert(fipc_channel >= 0); //!< 不可能失败
//!< 执行目标线程时用的是当前线程的资源,这里还需要备份当前线程的上下文。
ret = thread_fast_ipc_save(cur_th, to_task, (void *)(to_task->nofity_stack - 4 * 8 /*FIXME:改成宏*/)); //!< 备份栈和usp
if (ret >= 0)
{
ipc_msg_t *dst_ipc = (void *)to_task->nofity_msg_buf;
ipc_msg_t *dst_ipc = (void *)(to_task->nofity_msg_buf + fipc_channel * THREAD_MSG_BUG_LEN);
ipc_msg_t *src_ipc = (void *)cur_th->msg.msg;
ret = ipc_dat_copy_raw(&to_task->obj_space, &cur_task->obj_space, to_task->lim,
dst_ipc, src_ipc, in_tag, FALSE);
@@ -530,7 +551,7 @@ msg_tag_t thread_fast_ipc_call(task_t *to_task, entry_frame_t *f, umword_t user_
(void *)to_task->nofity_stack, (void *)to_task->mm_space.mm_block);
usr_stask_point->rg0[0] = in_tag.raw;
usr_stask_point->rg0[1] = user_id;
usr_stask_point->rg0[2] = f->regs[2];
usr_stask_point->rg0[2] = fipc_channel;
usr_stask_point->rg0[3] = f->regs[3];
scheduler_get_current()->sched_reset = 2;
@@ -551,7 +572,7 @@ msg_tag_t thread_fast_ipc_call(task_t *to_task, entry_frame_t *f, umword_t user_
//! 寄存器传参数
f->regs[0] = in_tag.raw;
f->regs[1] = user_id;
f->regs[2] = f->regs[2];
f->regs[2] = fipc_channel;
f->regs[3] = f->regs[3];
}
// 切换mpu
@@ -581,9 +602,10 @@ msg_tag_t thread_fast_ipc_call(task_t *to_task, entry_frame_t *f, umword_t user_
mutex_unlock(&to_task->nofity_lock);
sema_up(&to_task->notify_sema);
}
return msg_tag_init4(0, 0, 0, ret);
}
msg_tag_t thread_fast_ipc_replay(entry_frame_t *f)
{
task_t *cur_task = thread_get_current_task();
@@ -591,10 +613,16 @@ msg_tag_t thread_fast_ipc_replay(entry_frame_t *f)
msg_tag_t in_tag = msg_tag_init(f->regs[0]);
task_t *old_task = thread_get_bind_task(cur_th);
int ret;
int fipc_channel = f->regs[2];
if (fipc_channel < 0 || fipc_channel >= old_task->nofity_bitmap_len)
{
/*FIXME:应该在内核里面存这个值fipc_channel */
printk("panic : %s:%d fipc_channel:%d\n", __func__, __LINE__, fipc_channel);
return msg_tag_init4(0, 0, 0, -EINVAL);
}
assert(cur_th->magic == THREAD_MAGIC);
*(cur_task->nofity_bitmap) &= ~(1 << MIN(f->regs[2], cur_task->nofity_bitmap_len)); //!< 解锁bitmap
slist_del(&cur_th->com->fast_ipc_node); // 从链表中删除
ret = thread_fast_ipc_restore(cur_th); // 还原栈和usp
if (ret < 0)
@@ -607,21 +635,26 @@ msg_tag_t thread_fast_ipc_replay(entry_frame_t *f)
cur_task = thread_get_current_task();
ipc_msg_t *dst_ipc = (void *)cur_th->msg.msg;
ipc_msg_t *src_ipc = (void *)old_task->nofity_msg_buf;
ipc_msg_t *src_ipc = (void *)(old_task->nofity_msg_buf + fipc_channel * THREAD_MSG_BUG_LEN);
ret = ipc_dat_copy_raw(&cur_task->obj_space, &old_task->obj_space, cur_task->lim,
dst_ipc, src_ipc, in_tag, TRUE); // copy数据
fipc_free_channle(old_task, fipc_channel);
slist_del(&cur_th->com->fast_ipc_node); //!< 从链表中删除
// if (ret >=0 ) {
for (int i = 0; i < CONFIG_THREAD_MAP_BUF_LEN; i++)
{
// 映射了多少个,则重新填充多少个新的
if (i < ret)
{
src_ipc->map_buf[i] = old_task->nofity_map_buf[i];
old_task->nofity_map_buf[i] = 0;
src_ipc->map_buf[i] = old_task->nofity_map_buf[fipc_channel][i];
/*FIXME: 这里暂时倒序赋值因为用第一个值可能存在nofity_map_buf设置成0时另一个线程回复的时候会把这个0值用上 */
old_task->nofity_map_buf[fipc_channel][i] = 0;
}
else
{
src_ipc->map_buf[i] = old_task->nofity_map_buf[i];
src_ipc->map_buf[i] = old_task->nofity_map_buf[fipc_channel][i];
}
}
// }