修复fipc并发通信时映射错错乱的问题
This commit is contained in:
@@ -8,7 +8,6 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
|
||||
-Wno-builtin-declaration-mismatch \
|
||||
")
|
||||
|
||||
# -O1 \
|
||||
# -Ofast \
|
||||
# message(编译参数:${CMAKE_C_FLAGS})
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user