线程增加ipc能力,原ipc对象将修改为ipc代理功能

This commit is contained in:
zhangzheng
2023-11-26 00:15:32 +08:00
parent 782ef1331d
commit 5a0ad76ad0
16 changed files with 569 additions and 113 deletions

View File

@@ -15,11 +15,13 @@ typedef long long int64_t;
typedef unsigned long umword_t;
typedef unsigned short uhmword_t;
typedef long mword_t;
typedef short uhumword_t;
typedef signed long int intptr_t;
typedef unsigned long int uintptr_t;
typedef umword_t size_t;
typedef mword_t ssize_t;
typedef umword_t ptr_t;
typedef char bool_t;
typedef unsigned long obj_addr_t;

View File

@@ -15,6 +15,7 @@ void SysTick_Handler(void)
// 进行上下文切换
thread_sched();
sys_tick_cnt++;
thread_timeout_check();
timeout_times_tick();
futex_timeout_times_tick();
}

View File

@@ -15,6 +15,7 @@ void SysTick_Handler(void)
// 进行上下文切换
thread_sched();
sys_tick_cnt++;
thread_timeout_check(1);
timeout_times_tick();
futex_timeout_times_tick();
}

View File

@@ -2,50 +2,4 @@
#include "thread.h"
#include "types.h"
#define IPC_MSG_SIZE 96
#define MAP_BUF_SIZE 16
#define IPC_USER_SIZE 12
#if (IPC_MSG_SIZE + MAP_BUF_SIZE + IPC_USER_SIZE) > THREAD_MSG_BUG_LEN
#error "IPC MSG len error."
#endif
typedef struct ipc_msg
{
union
{
struct
{
umword_t msg_buf[IPC_MSG_SIZE / WORD_BYTES];
umword_t map_buf[MAP_BUF_SIZE / WORD_BYTES];
umword_t user[IPC_USER_SIZE / WORD_BYTES];
};
uint8_t data[THREAD_MSG_BUG_LEN];
};
} ipc_msg_t;
typedef union ipc_timeout
{
umword_t raw;
struct
{
uhmword_t send_timeout;
uhmword_t recv_timeout;
};
} ipc_timeout_t;
static inline ipc_timeout_t ipc_timeout_create2(uhmword_t send_timeout, uhmword_t recv_timeout)
{
return (ipc_timeout_t){
.send_timeout = send_timeout,
.recv_timeout = recv_timeout,
};
}
static inline ipc_timeout_t ipc_timeout_create(umword_t raw)
{
return (ipc_timeout_t){
.raw = raw,
};
}
void timeout_times_tick(void);

View File

@@ -39,6 +39,7 @@ enum knl_obj_type
MM_TYPE,
FACTORY_TYPE,
SYS_TYPE,
FUTEX_TYPE,
};
typedef struct kobject

View File

@@ -69,3 +69,4 @@ void obj_space_del(obj_space_t *obj_space, obj_addr_t inx);
obj_map_entry_t *obj_space_insert(obj_space_t *obj_space, ram_limit_t *ram, kobject_t *kobj, obj_addr_t inx, uint8_t attrs);
obj_map_entry_t *obj_space_lookup(obj_space_t *obj_space, obj_addr_t inx);
kobject_t *obj_space_lookup_kobj(obj_space_t *obj_space, obj_addr_t inx);
kobject_t *obj_space_lookup_kobj_cmp_type(obj_space_t *obj_space, obj_addr_t inx, enum knl_obj_type obj_type);

View File

@@ -21,13 +21,73 @@ typedef struct task task_t;
struct thread;
typedef struct thread thread_t;
#define THREAD_MSG_BUG_LEN 128UL //!< 最小的消息寄存器大小
#define MSG_BUF_HAS_DATA_FLAGS 0x01U //!< 已经有数据了
#define MSG_BUF_RECV_R_FLAGS 0x02U //!< 接收来自recv_th的消息
#define MSG_BUF_REPLY_FLAGS 0x04U //!< 回复消息给send_th
#define IPC_MSG_SIZE 96
#define MAP_BUF_SIZE 16
#define IPC_USER_SIZE 12
#if (IPC_MSG_SIZE + MAP_BUF_SIZE + IPC_USER_SIZE) > THREAD_MSG_BUG_LEN
#error "IPC MSG len error."
#endif
typedef struct ipc_msg
{
union
{
struct
{
umword_t msg_buf[IPC_MSG_SIZE / WORD_BYTES];
umword_t map_buf[MAP_BUF_SIZE / WORD_BYTES];
umword_t user[IPC_USER_SIZE / WORD_BYTES];
};
uint8_t data[THREAD_MSG_BUG_LEN];
};
} ipc_msg_t;
typedef union ipc_timeout
{
umword_t raw;
struct
{
uhmword_t send_timeout;
uhmword_t recv_timeout;
};
} ipc_timeout_t;
static inline ipc_timeout_t ipc_timeout_create2(uhmword_t send_timeout, uhmword_t recv_timeout)
{
return (ipc_timeout_t){
.send_timeout = send_timeout,
.recv_timeout = recv_timeout,
};
}
static inline ipc_timeout_t ipc_timeout_create(umword_t raw)
{
return (ipc_timeout_t){
.raw = raw,
};
}
enum thread_state
{
THREAD_IDLE, //!< 空闲状态
THREAD_DEAD, //!< 死亡状态
THREAD_SUSPEND, //!< 只有接收和发送ipc消息时才能挂起
THREAD_READY, //!< 在就绪队列中
THREAD_TODEAD, //!< 该标志标志线程马上要死亡了执行完必要操作后进入THREAD_DEAD状态
THREAD_IDLE = 0, //!< 空闲状态
THREAD_DEAD = 1, //!< 死亡状态
THREAD_SUSPEND = 2, //!< 只有接收和发送ipc消息时才能挂起
THREAD_READY = 3, //!< 在就绪队列中
THREAD_TODEAD = 4, //!< 该标志标志线程马上要死亡了执行完必要操作后进入THREAD_DEAD状态
};
enum thread_ipc_state
{
THREAD_NONE,
THREAD_SEND,
THREAD_RECV,
THREAD_WAIT,
THREAD_TIMEOUT,
THREAD_IPC_ABORT,
};
typedef struct
{
@@ -50,11 +110,6 @@ typedef struct sp_info
mword_t sp_type; //!< 使用的栈类型
} sp_info_t;
#define THREAD_MSG_BUG_LEN 128UL //!< 默认的消息寄存器大小
#define MSG_BUF_HAS_DATA_FLAGS 0x01U //!< 已经有数据了
#define MSG_BUF_RECV_R_FLAGS 0x02U //!< 接收来自recv_th的消息
#define MSG_BUF_REPLY_FLAGS 0x04U //!< 回复消息给send_th
typedef struct msg_buf
{
void *msg; //!< buf长度是固定的 @see THREAD_MSG_BUG_LEN
@@ -70,8 +125,16 @@ typedef struct thread
sp_info_t sp; //!< sp信息
ram_limit_t *lim; //!< 内存限制
ref_counter_t ref; //!< 引用计数
msg_buf_t msg; //!< 每个线程独有的消息缓存区
slist_head_t wait_send; //!< 节点
slist_head_t wait_head; //!< 里面是等待发送给当前线程数据的线程们。
mword_t ipc_times; //!< ipc时间
thread_t *last_send_th; //!< 当前线程上次接收到谁的数据
enum thread_state status; //!< 线程状态
enum thread_ipc_state ipc_status; //!< ipc状态
umword_t magic; //!< maigc
} thread_t;
@@ -120,3 +183,5 @@ void thread_suspend(thread_t *th);
void thread_dead(thread_t *th);
void thread_todead(thread_t *th, bool_t is_sche);
void thread_ready(thread_t *th, bool_t is_sche);
void thread_timeout_check(ssize_t tick);

View File

@@ -20,6 +20,7 @@ typedef signed long int intptr_t;
typedef unsigned long int uintptr_t;
typedef umword_t size_t;
typedef mword_t ssize_t;
typedef umword_t ptr_t;
typedef char bool_t;
typedef unsigned long obj_addr_t;

View File

@@ -445,7 +445,7 @@ static void futex_release_stage2(kobject_t *kobj)
}
static void futex_init(futex_t *ft)
{
kobject_init(&ft->kobj, IPC_TYPE);
kobject_init(&ft->kobj, FUTEX_TYPE);
spinlock_init(&ft->lock);
ft->kobj.invoke_func = futex_syscall;
ft->kobj.stage_1_func = futex_release_stage1;

View File

@@ -277,8 +277,8 @@ static int ipc_data_copy(thread_t *dst_th, thread_t *src_th, msg_tag_t tag)
static msg_tag_t ipc_call(ipc_t *ipc, thread_t *th, entry_frame_t *f, msg_tag_t tag, ipc_timeout_t timeout)
{
umword_t status;
int ret = -1;
msg_tag_t tmp_tag;
int ret = -1;
assert(th != ipc->svr_th);
status = spinlock_lock(&ipc->lock);

View File

@@ -103,3 +103,17 @@ kobject_t *obj_space_lookup_kobj(obj_space_t *obj_space, obj_addr_t inx)
}
return obj_map_kobj_get(entry_obj->obj);
}
kobject_t *obj_space_lookup_kobj_cmp_type(obj_space_t *obj_space, obj_addr_t inx, enum knl_obj_type obj_type)
{
kobject_t *kobj = obj_space_lookup_kobj(obj_space, inx);
if (!kobj)
{
return NULL;
}
if (kobj->kobj_type != obj_type)
{
return NULL;
}
return kobj;
}

View File

@@ -23,6 +23,18 @@
#include "thread_armv7m.h"
#include "assert.h"
#include "err.h"
#include "map.h"
enum thread_op
{
SET_EXEC_REGS,
RUN_THREAD,
BIND_TASK,
MSG_BUG_GET,
MSG_BUG_SET,
YIELD,
DO_IPC,
};
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);
@@ -36,7 +48,8 @@ void thread_init(thread_t *th, ram_limit_t *lim)
{
kobject_init(&th->kobj, THREAD_TYPE);
sched_init(&th->sche);
// slist_init(&th->wait);
slist_init(&th->wait_send);
slist_init(&th->wait_head);
ref_counter_init(&th->ref);
ref_counter_inc(&th->ref);
th->lim = lim;
@@ -58,30 +71,28 @@ static void thread_release_stage1(kobject_t *kobj)
thread_t *cur = thread_get_current();
kobject_invalidate(kobj);
if (cur == th)
if (cur != th)
{
if (th->status == THREAD_READY || th->status == THREAD_TODEAD)
//! 线程在运行中,则挂起线程
if (th->status == THREAD_READY)
{
thread_dead(th);
}
}
else
{
if (th->status == THREAD_TODEAD) //!< 如果在TODEAD状态则等待其死亡
{
while (th->status != THREAD_DEAD)
{
//!< 循环等待其死亡
thread_sched();
preemption();
}
}
else if (th->status == THREAD_READY)
{
thread_dead(th);
thread_suspend(th);
}
}
thread_t *pos;
slist_foreach_not_next(pos, &th->wait_head, wait_send)
{
assert(pos->status == THREAD_SUSPEND);
thread_t *next = slist_next_entry(pos, &th->wait_head, wait_send);
pos->ipc_status = THREAD_IPC_ABORT;
thread_ready(pos, TRUE);
slist_del(&pos->wait_send);
pos = next;
}
slist_del(&th->wait_send); //!< 从链表中删除
thread_unbind(th);
}
static void thread_release_stage2(kobject_t *kobj)
@@ -243,15 +254,346 @@ thread_t *thread_create(ram_limit_t *ram)
printk("create thread 0x%x\n", th);
return th;
}
enum thread_op
enum IPC_TYPE
{
SET_EXEC_REGS,
RUN_THREAD,
BIND_TASK,
MSG_BUG_GET,
MSG_BUG_SET,
YIELD,
IPC_CALL,
IPC_REPLY,
IPC_WAIT,
IPC_RECV,
IPC_SEND,
};
void thread_timeout_check(ssize_t tick)
{
thread_t *pos;
thread_t *th = thread_get_current();
slist_foreach_not_next(pos, &th->wait_head, wait_send)
{
assert(pos->status == THREAD_SUSPEND);
thread_t *next = slist_next_entry(pos, &th->wait_head, wait_send);
if (pos->ipc_times > 0)
{
pos->ipc_times -= tick;
if (pos->ipc_times <= 0)
{
pos->ipc_status = THREAD_TIMEOUT;
thread_ready(pos, TRUE);
slist_del(&pos->wait_send);
}
}
pos = next;
}
}
/**
* @brief ipc传输时的数据拷贝
*
* @param dst_th
* @param src_th
* @param tag
* @return int
*/
static int ipc_data_copy(thread_t *dst_th, thread_t *src_th, msg_tag_t tag)
{
void *src = src_th->msg.msg;
void *dst = dst_th->msg.msg;
ipc_msg_t *src_ipc;
ipc_msg_t *dst_ipc;
src_ipc = src;
dst_ipc = dst;
if (tag.map_buf_len > 0)
{
kobj_del_list_t del;
int map_len = tag.map_buf_len;
kobj_del_list_init(&del);
task_t *src_tk = thread_get_bind_task(src_th);
task_t *dst_tk = thread_get_bind_task(dst_th);
for (int i = 0; i < map_len; i++)
{
int ret = 0;
vpage_t dst_page = vpage_create_raw(dst_ipc->map_buf[i]);
vpage_t src_page = vpage_create_raw(src_ipc->map_buf[i]);
if (src_page.flags & VPAGE_FLAGS_MAP)
{
ret = obj_map_src_dst(&dst_tk->obj_space, &src_tk->obj_space,
vpage_get_obj_handler(dst_page),
vpage_get_obj_handler(src_page),
dst_tk->lim,
vpage_get_attrs(src_page), &del);
}
if (ret < 0)
{
return ret;
}
}
kobj_del_list_to_do(&del);
}
memcpy(dst_ipc->msg_buf, src_ipc->msg_buf, MIN(tag.msg_buf_len * WORD_BYTES, IPC_MSG_SIZE));
return 0;
}
/**
* @brief 当前线程接收数据
*
* @return int
*/
static int thread_ipc_recv(msg_tag_t *ret_msg)
{
assert(ret_msg);
thread_t *cur_th = thread_get_current();
umword_t lock_status;
lock_status = cpulock_lock();
cur_th->ipc_status = THREAD_RECV; //!< 因为接收挂起
thread_suspend(cur_th); //!< 挂起
if (!slist_is_empty(&cur_th->wait_head))
{
slist_head_t *mslist = slist_first(&cur_th->wait_head);
thread_t *send_th = container_of(mslist, thread_t, wait_send);
slist_del(mslist); //!< 删除唤醒的线程
thread_ready(send_th, TRUE);
}
preemption(); //!< 进行调度
cur_th->ipc_status = THREAD_NONE;
*ret_msg = cur_th->msg.tag;
cpulock_set(lock_status);
return 0;
}
/**
* @brief 当前线程回复数据给上一次的发送者,回复完成后则释放上一次的接收者指针
*
* @param in_tag
* @return int
*/
static int thread_ipc_reply(msg_tag_t in_tag)
{
thread_t *cur_th = thread_get_current();
umword_t status;
if (cur_th->last_send_th == NULL)
{
return -1;
}
status = cpulock_lock();
if (cur_th->last_send_th == NULL)
{
cpulock_set(status);
return -1;
}
assert(cur_th->last_send_th->status == THREAD_SUSPEND);
assert(cur_th->last_send_th->ipc_status == THREAD_RECV);
//!< 发送数据给上一次的发送者
int ret = ipc_data_copy(cur_th->last_send_th, cur_th, in_tag); //!< 拷贝数据
if (ret < 0)
{
cpulock_set(status);
return ret;
}
cur_th->last_send_th->msg.tag = in_tag;
thread_ready(cur_th->last_send_th, TRUE); //!< 直接唤醒接受者
ref_counter_dec_and_release(&cur_th->last_send_th->ref, &cur_th->last_send_th->kobj);
cur_th->last_send_th = NULL;
cpulock_set(status);
return ret;
}
static int thread_ipc_send(obj_handler_t target_th_hd, msg_tag_t in_tag, ipc_timeout_t timout)
{
int ret = -EINVAL;
task_t *cur_task = thread_get_current_task();
thread_t *cur_th = thread_get_current();
mword_t lock_stats = spinlock_lock(&cur_task->kobj.lock);
thread_t *recv_kobj;
if (lock_stats < 0)
{
//!< 锁已经无效了
return -EACCES;
}
ref_counter_inc(&cur_task->ref_cn);
recv_kobj = (thread_t *)obj_space_lookup_kobj_cmp_type(&cur_task->obj_space, target_th_hd, THREAD_TYPE);
if (!recv_kobj) /*比较类型*/
{
return -ENOENT;
}
again_check:
if (recv_kobj->status == THREAD_READY)
{
cur_th->ipc_status = THREAD_SEND; //!< 因为发送挂起
cur_th->ipc_times = timout.send_timeout;
thread_suspend(cur_th); //!< 挂起
slist_add_append(&recv_kobj->wait_head, &cur_th->wait_send); //!< 放到等待队列中
preemption(); //!< 进行调度
if (cur_th->ipc_status == THREAD_IPC_ABORT)
{
ret = -ESHUTDOWN;
goto end;
}
else if (cur_th->ipc_status == THREAD_TIMEOUT)
{
ret = -EWTIMEDOUT;
goto end;
}
cur_th->ipc_status = THREAD_NONE;
goto again_check;
}
else if (recv_kobj->status == THREAD_SUSPEND && recv_kobj->ipc_status == THREAD_RECV)
{
//!< 开始发送数据
ret = ipc_data_copy(recv_kobj, cur_th, in_tag); //!< 拷贝数据
if (ret < 0)
{
//!< 拷贝失败
goto end;
}
thread_ready(recv_kobj, TRUE); //!< 直接唤醒接受者
preemption(); //!< 进行调度
}
ret = 0;
end:
spinlock_set(&cur_task->kobj.lock, lock_stats);
ref_counter_dec_and_release(&cur_task->ref_cn, &cur_task->kobj);
return ret;
}
static int thread_ipc_call(obj_handler_t target_th_hd, msg_tag_t in_tag, msg_tag_t *ret_tag, ipc_timeout_t timout)
{
assert(ret_tag);
int ret = -EINVAL;
task_t *cur_task = thread_get_current_task();
thread_t *cur_th = thread_get_current();
thread_t *recv_kobj;
mword_t lock_stats = spinlock_lock(&cur_task->kobj.lock);
if (lock_stats < 0)
{
//!< 锁已经无效了
return -EACCES;
}
ref_counter_inc(&cur_task->ref_cn);
recv_kobj = (thread_t *)obj_space_lookup_kobj_cmp_type(&cur_task->obj_space, target_th_hd, THREAD_TYPE);
if (!recv_kobj) /*比较类型*/
{
ret = -ENOENT;
goto end;
}
again_check:
if (recv_kobj->status == THREAD_READY)
{
cur_th->ipc_status = THREAD_SEND; //!< 因为发送挂起
cur_th->ipc_times = timout.send_timeout;
thread_suspend(cur_th); //!< 挂起
slist_add_append(&recv_kobj->wait_head, &cur_th->wait_send); //!< 放到等待队列中
preemption(); //!< 进行调度
if (cur_th->ipc_status == THREAD_IPC_ABORT)
{
cur_th->ipc_status = THREAD_NONE;
ret = -ESHUTDOWN;
goto end;
}
else if (cur_th->ipc_status == THREAD_TIMEOUT)
{
ret = -EWTIMEDOUT;
goto end;
}
cur_th->ipc_status = THREAD_NONE;
goto again_check;
}
else if (recv_kobj->status == THREAD_SUSPEND && recv_kobj->ipc_status == THREAD_RECV)
{
//!< 开始发送数据
ret = ipc_data_copy(recv_kobj, cur_th, in_tag); //!< 拷贝数据
if (ret < 0)
{
//!< 拷贝失败
goto end;
}
recv_kobj->last_send_th = cur_th; //!< 设置接收者的上一次发送者是谁
ref_counter_inc(&cur_th->ref); //!< 作为发送者增加一次引用
thread_ready(recv_kobj, TRUE); //!< 直接唤醒接受者
thread_ipc_recv(ret_tag); //!< 当前线程进行接收
preemption(); //!< 进行调度
}
ret = 0;
end:
spinlock_set(&cur_task->kobj.lock, lock_stats);
ref_counter_dec_and_release(&cur_task->ref_cn, &cur_task->kobj);
return ret;
}
/**
* @brief 执行ipc
*
* @param kobj
* @param in_tag
* @param f
* @return int
*/
static msg_tag_t thread_do_ipc(kobject_t *kobj, entry_frame_t *f)
{
assert(kobj);
task_t *cur_task = thread_get_current_task();
thread_t *cur_th = thread_get_current();
umword_t ipc_type = f->r[1];
obj_handler_t th_hd = 0;
int ret = -EINVAL;
switch (ipc_type)
{
case IPC_CALL:
{
msg_tag_t in_tag = msg_tag_init(f->r[0]);
msg_tag_t recv_tag;
th_hd = f->r[2];
ipc_timeout_t ipc_tm_out = ipc_timeout_create(f->r[3]);
ret = thread_ipc_call(th_hd, in_tag, &recv_tag, ipc_tm_out);
if (ret < 0)
{
return msg_tag_init4(0, 0, 0, ret);
}
return recv_tag;
}
case IPC_REPLY:
{
msg_tag_t in_tag = msg_tag_init(f->r[0]);
ret = thread_ipc_reply(in_tag);
return msg_tag_init4(0, 0, 0, ret);
}
case IPC_RECV:
case IPC_WAIT:
{
msg_tag_t ret_msg;
thread_ipc_recv(&ret_msg);
return ret_msg;
}
case IPC_SEND:
{
msg_tag_t in_tag = msg_tag_init(f->r[0]);
ipc_timeout_t ipc_tm_out = ipc_timeout_create(f->r[3]);
th_hd = f->r[2];
ret = thread_ipc_send(th_hd, in_tag, ipc_tm_out);
return msg_tag_init4(0, 0, 0, ret);
}
default:
ret = -ENOSYS;
break;
}
return msg_tag_init4(0, 0, 0, ret);
}
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);
@@ -330,6 +672,11 @@ static void thread_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_t
tag = msg_tag_init4(0, 0, 0, 0);
}
break;
case DO_IPC:
{
tag = thread_do_ipc(&cur_th->kobj, f);
}
break;
}
f->r[0] = tag.raw;
}

View File

@@ -2,7 +2,7 @@
#include "u_types.h"
#include "u_prot.h"
#include "u_ipc.h"
msg_tag_t thread_yield(obj_handler_t obj);
msg_tag_t thread_msg_buf_set(obj_handler_t obj, void *msg);
msg_tag_t thread_msg_buf_get(obj_handler_t obj, umword_t *msg, umword_t *len);
@@ -10,6 +10,11 @@ msg_tag_t thread_exec_regs(obj_handler_t obj, umword_t pc, umword_t sp, umword_t
msg_tag_t thread_run(obj_handler_t obj, uint8_t prio);
msg_tag_t thread_bind_task(obj_handler_t obj, obj_handler_t tk_obj);
msg_tag_t thread_ipc_wait(void);
msg_tag_t thread_ipc_reply(msg_tag_t in_tag, ipc_timeout_t timeout);
msg_tag_t thread_ipc_send(msg_tag_t in_tag, obj_handler_t target_th_obj, ipc_timeout_t timeout);
msg_tag_t thread_ipc_call(msg_tag_t in_tag, obj_handler_t target_th_obj, ipc_timeout_t timeout);
#define thread_get_cur_ipc_msg() \
( \
{ \

View File

@@ -1,6 +1,7 @@
#include "u_prot.h"
#include "u_types.h"
#include "u_thread.h"
#include "u_ipc.h"
enum thread_op
{
SET_EXEC_REGS,
@@ -9,7 +10,80 @@ enum thread_op
MSG_BUG_GET,
MSG_BUG_SET,
YIELD,
DO_IPC,
};
enum IPC_TYPE
{
IPC_CALL,
IPC_REPLY,
IPC_WAIT,
IPC_RECV,
IPC_SEND,
};
msg_tag_t thread_ipc_wait(void)
{
register volatile umword_t r0 asm("r0");
mk_syscall(syscall_prot_create4(DO_IPC, THREAD_PROT, -1, TRUE).raw,
0,
IPC_WAIT,
0,
0,
0,
0);
asm __volatile__(""
:
:
: "r0");
return msg_tag_init(r0);
}
msg_tag_t thread_ipc_reply(msg_tag_t in_tag, ipc_timeout_t timeout)
{
register volatile umword_t r0 asm("r0");
mk_syscall(syscall_prot_create4(DO_IPC, THREAD_PROT, -1, TRUE).raw,
in_tag.raw,
IPC_REPLY,
0,
timeout.raw,
0,
0);
asm __volatile__(""
:
:
: "r0");
return msg_tag_init(r0);
}
msg_tag_t thread_ipc_send(msg_tag_t in_tag, obj_handler_t target_th_obj, ipc_timeout_t timeout)
{
register volatile umword_t r0 asm("r0");
mk_syscall(syscall_prot_create4(DO_IPC, THREAD_PROT, -1, TRUE).raw,
in_tag.raw,
IPC_SEND,
target_th_obj,
timeout.raw,
0,
0);
asm __volatile__(""
:
:
: "r0");
return msg_tag_init(r0);
}
msg_tag_t thread_ipc_call(msg_tag_t in_tag, obj_handler_t target_th_obj, ipc_timeout_t timeout)
{
register volatile umword_t r0 asm("r0");
mk_syscall(syscall_prot_create4(DO_IPC, THREAD_PROT, -1, TRUE).raw,
in_tag.raw,
IPC_CALL,
target_th_obj,
timeout.raw,
0,
0);
asm __volatile__(""
:
:
: "r0");
return msg_tag_init(r0);
}
msg_tag_t thread_yield(obj_handler_t obj)
{
register volatile umword_t r0 asm("r0");

View File

@@ -35,10 +35,10 @@ int main(int argc, char *args[])
mpu_test();
thread_press_test();
kobj_create_press_test();
ipc_test();
pthread_cond_lock_test();
pthread_lock_test();
#endif
ipc_test();
uenv_t env = *u_get_global_env();
obj_handler_t ipc_hd;
int ret = rpc_creaite_bind_ipc(THREAD_MAIN, NULL, &ipc_hd);

View File

@@ -69,7 +69,7 @@ static void thread_test_func2(void)
static void hard_sleep(void)
{
for (volatile int i; i < 10000000; i++)
for (volatile int i; i < 1000000000; i++)
;
}
static void thread_test_func(void)
@@ -79,10 +79,10 @@ static void thread_test_func(void)
thread_msg_buf_get(th1_hd, (umword_t *)(&buf), NULL);
while (1)
{
ipc_wait(ipc_hd, 0);
thread_ipc_wait();
printf("srv recv:%s", buf);
hard_sleep();
ipc_reply(ipc_hd, msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0));
thread_ipc_reply(msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0), ipc_timeout_create2(0, 0));
}
printf("thread_test_func.\n");
task_unmap(TASK_PROT, vpage_create_raw3(KOBJ_DELETE_RIGHT, 0, th1_hd));
@@ -96,7 +96,7 @@ static void thread_test_func2(void)
while (1)
{
strcpy(buf, "I am th2.\n");
ipc_call(ipc_hd, msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0), ipc_timeout_create2(0, 0));
thread_ipc_call(msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0), th1_hd, ipc_timeout_create2(0, 0));
printf("th2:%s", buf);
}
printf("thread_test_func2.\n");
@@ -113,7 +113,7 @@ static void thread_test_func3(void)
while (1)
{
strcpy(buf, "I am th3.\n");
ipc_call(ipc_hd, msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0), ipc_timeout_create2(0, 0));
thread_ipc_call(msg_tag_init4(0, ROUND_UP(strlen(buf), WORD_BYTES), 0, 0), th1_hd, ipc_timeout_create2(0, 0));
printf("th3:%s", buf);
}
printf("thread_test_func2.\n");
@@ -127,17 +127,14 @@ static void thread_test_func3(void)
*/
void ipc_test(void)
{
msg_tag_t tag;
th1_hd = handler_alloc();
assert(th1_hd != HANDLER_INVALID);
th2_hd = handler_alloc();
assert(th2_hd != HANDLER_INVALID);
th3_hd = handler_alloc();
assert(th3_hd != HANDLER_INVALID);
ipc_hd = handler_alloc();
assert(ipc_hd != HANDLER_INVALID);
msg_tag_t tag = factory_create_ipc(FACTORY_PROT, vpage_create_raw3(KOBJ_ALL_RIGHTS, 0, ipc_hd));
assert(msg_tag_get_prot(tag) >= 0);
tag = factory_create_thread(FACTORY_PROT, vpage_create_raw3(KOBJ_ALL_RIGHTS, 0, th1_hd));
assert(msg_tag_get_prot(tag) >= 0);
ipc_bind(ipc_hd, th1_hd, 0);
@@ -176,11 +173,4 @@ void ipc_test(void)
void ipc_timeout_test(void)
{
obj_handler_t hd = handler_alloc();
factory_create_ipc(FACTORY_PROT, vpage_create_raw3(KOBJ_ALL_RIGHTS, 0, hd));
printf("sleep.\n");
ipc_call(hd, msg_tag_init4(0, 0, 0, 0), ipc_timeout_create2(100, 100));
printf("sleep.\n");
ipc_call(hd, msg_tag_init4(0, 0, 0, 0), ipc_timeout_create2(100, 100));
handler_free_umap(hd);
}