ipc支持send

This commit is contained in:
zhangzheng
2023-11-19 13:57:34 +08:00
parent 3a70b7d297
commit 1b82ecbbda
9 changed files with 216 additions and 51 deletions

View File

@@ -33,13 +33,16 @@ static inline mword_t slist_is_empty(slist_head_t *list)
*/
static inline bool_t slist_in_list(slist_head_t *item)
{
if (slist_is_empty(item)) {
if (slist_is_empty(item))
{
return FALSE;
}
if (item->prev->next != item) {
if (item->prev->next != item)
{
return FALSE;
}
if (item->next->prev != item) {
if (item->next->prev != item)
{
return FALSE;
}
return TRUE;
@@ -59,9 +62,9 @@ static inline void slist_add(slist_head_t *head, slist_head_t *item)
}
static inline void slist_add_append(slist_head_t *head, slist_head_t *item)
{
slist_head_t *tail = head->prev;
slist_head_t *tail = head->prev;
return slist_add(tail, item);
return slist_add(tail, item);
}
/**
* @brief 获取第一个节点
@@ -93,5 +96,14 @@ static inline void slist_del(slist_head_t *item)
/**
* @brief 遍历每一个节点获得struct的入口
*/
#define slist_foreach(pos, head, member) \
for (pos = slist_entry((head)->next, typeof(*pos), member); &(pos)->member != (head) && !slist_is_empty(head); pos = slist_entry((pos)->member.next, typeof(*pos), member))
#define slist_foreach(pos, head, member) \
for (pos = slist_entry((head)->next, typeof(*pos), member); \
&(pos)->member != (head) && !slist_is_empty(head); \
pos = slist_entry((pos)->member.next, typeof(*pos), member))
#define slist_foreach_not_next(pos, head, member) \
for (pos = slist_entry((head)->next, typeof(*pos), member); \
&(pos)->member != (head) && !slist_is_empty(head);)
#define slist_next_entry(pos, head, member) \
slist_entry((pos)->member.next, typeof(*pos), member)

View File

@@ -54,6 +54,7 @@ enum ipc_op
IPC_REPLY, //!< 服务端回复信息
IPC_BIND, //!< 绑定服务端线程
IPC_UNBIND, //!< 解除绑定
IPC_SEND, //!<
};
static int wake_up_th(ipc_t *ipc);
static slist_head_t wait_list;
@@ -94,7 +95,10 @@ void timeout_times_tick(void)
else
{
//!< 超时时间满后直接唤醒等待者
thread_ready(item->th, TRUE);
if (item->th->status == THREAD_SUSPEND)
{
thread_ready(item->th, TRUE);
}
}
}
spinlock_set(&ipc->lock, status);
@@ -150,11 +154,9 @@ static void ipc_wait_item_init(ipc_wait_item_t *item, ipc_t *ipc, thread_t *th,
* @param head
* @param th
* @param times 超时时间为0代表一直超时
* @param lock
* @param status
* @return int
*/
static int add_wait_unlock(ipc_t *ipc, slist_head_t *head, thread_t *th, umword_t times, spinlock_t *lock, int status)
static int add_wait_unlock(ipc_t *ipc, slist_head_t *head, thread_t *th, umword_t times, bool_t set_last_th)
{
int ret = 0;
ipc_wait_item_t item;
@@ -169,8 +171,9 @@ static int add_wait_unlock(ipc_t *ipc, slist_head_t *head, thread_t *th, umword_
}
slist_add_append(head, &item.node);
thread_suspend(th);
spinlock_set(lock, status);
preemption();
slist_del(&item.node);
// spinlock_set(lock, status);
if (times)
{
if (slist_is_empty(head))
@@ -204,7 +207,10 @@ static int wake_up_th(ipc_t *ipc)
}
else
{
thread_ready(item->th, TRUE);
if (item->th->status == THREAD_SUSPEND)
{
thread_ready(item->th, TRUE);
}
}
return 0;
}
@@ -275,14 +281,15 @@ static msg_tag_t ipc_call(ipc_t *ipc, thread_t *th, entry_frame_t *f, msg_tag_t
msg_tag_t tmp_tag;
assert(th != ipc->svr_th);
__check:
status = spinlock_lock(&ipc->lock);
__check:
if (ipc->svr_th == NULL || ipc->svr_th->status != THREAD_SUSPEND)
{
ret = add_wait_unlock(ipc, &ipc->wait_send, th,
timeout.send_timeout, &ipc->lock, status);
timeout.send_timeout, FALSE);
if (ret < 0)
{
spinlock_set(&ipc->lock, status);
return msg_tag_init4(MSG_TAG_KNL_ERR, 0, 0, ret);
}
goto __check;
@@ -298,16 +305,51 @@ __check:
ipc->svr_th->msg.tag = tag;
thread_ready(ipc->svr_th, TRUE); //!< 直接唤醒接受者
ipc->last_cli_th = th; //!< 设置上一次发送的客户端
ret = add_wait_unlock(ipc, &ipc->recv_send, th, timeout.recv_timeout, &ipc->lock, status);
ret = add_wait_unlock(ipc, &ipc->recv_send, th, timeout.recv_timeout, TRUE);
if (ret < 0)
{
// ref_counter_dec_and_release(&ipc->last_cli_th->ref, &ipc->last_cli_th->kobj);
ipc->last_cli_th = NULL;
spinlock_set(&ipc->lock, status);
return msg_tag_init4(MSG_TAG_KNL_ERR, 0, 0, ret);
}
// spinlock_set(&ipc->lock, status);
tmp_tag = th->msg.tag;
// ipc->last_cli_th = NULL;
spinlock_set(&ipc->lock, status);
return tmp_tag;
}
static msg_tag_t ipc_send(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;
assert(th != ipc->svr_th);
status = spinlock_lock(&ipc->lock);
__check:
if (ipc->svr_th == NULL || ipc->svr_th->status != THREAD_SUSPEND)
{
ret = add_wait_unlock(ipc, &ipc->wait_send, th,
timeout.send_timeout, FALSE);
if (ret < 0)
{
spinlock_set(&ipc->lock, status);
return msg_tag_init4(MSG_TAG_KNL_ERR, 0, 0, ret);
}
goto __check;
}
//!< 发送数据给svr_th
ret = ipc_data_copy(ipc->svr_th, th, tag); //!< 拷贝数据
if (ret < 0)
{
//!< 拷贝失败
spinlock_set(&ipc->lock, status);
return msg_tag_init4(MSG_TAG_KNL_ERR, 0, 0, ret);
}
ipc->svr_th->msg.tag = tag;
thread_ready(ipc->svr_th, TRUE); //!< 直接唤醒接受者
ipc->last_cli_th = NULL;
spinlock_set(&ipc->lock, status);
return tmp_tag;
}
/**
@@ -327,6 +369,11 @@ static int ipc_reply(ipc_t *ipc, thread_t *th, entry_frame_t *f, msg_tag_t tag)
}
assert(th == ipc->svr_th); // 服务端才能回复
status = spinlock_lock(&ipc->lock);
if (ipc->last_cli_th == NULL)
{
spinlock_set(&ipc->lock, status);
return -1;
}
//!< 发送数据给svr_th
int ret = ipc_data_copy(ipc->last_cli_th, th, tag); //!< 拷贝数据
@@ -428,6 +475,24 @@ static void ipc_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag,
}
}
break;
case IPC_SEND:
{
if (th == ipc->svr_th)
{
tag = msg_tag_init4(0, 0, 0, -EACCES);
}
else
{
ref_counter_inc(&th->ref); //!< 引用计数+1
tag = ipc_send(ipc, th, f, in_tag, ipc_timeout_create(f->r[1])); //!< ipc call
ref_counter_dec_and_release(&th->ref, &th->kobj); //!< 引用计数-1
if (msg_tag_get_val(tag) == -ESHUTDOWN)
{
thread_dead(th);
}
}
}
break;
case IPC_WAIT:
{
if (ipc->svr_th != th) //!< 只有服务端才能wait
@@ -530,6 +595,7 @@ static void ipc_init(ipc_t *ipc, ram_limit_t *lim)
kobject_init(&ipc->kobj, IPC_TYPE);
slist_init(&ipc->wait_send);
slist_init(&ipc->recv_send);
slist_init(&ipc->node);
spinlock_init(&ipc->lock);
ipc->lim = lim;
ipc->svr_th = NULL;

View File

@@ -1,3 +1,13 @@
/**
* @file syscall.c
* @author zhangzheng (1358745329@qq.com)
* @brief
* @version 0.1
* @date 2023-11-19
*
* @copyright Copyright (c) 2023
*
*/
#include "types.h"
#include "syscall.h"
#include "thread.h"

View File

@@ -20,6 +20,7 @@
#include <pthread.h>
#include <futex.h>
#include <assert.h>
#include <limits.h>
#define FT_NR 16
static obj_handler_t hd_futex_ipc;
@@ -110,13 +111,65 @@ static futex_lock_t *futex_find(futex_t *ft, void *uaddr)
}
return NULL;
}
void futex_svr_thread(void)
static void futex_svr_thread(void)
{
ipc_msg_t *msg;
uint32_t *uaddr;
int futex_op;
uint32_t val;
const struct timespec *timeout; /*or val2*/
uint32_t uaddr2;
uint32_t val3;
ulog_write_str(LOG_PROT, "futex running..\n");
thread_msg_buf_get(-1, (umword_t *)(&msg), NULL);
while (1)
{
ipc_wait(hd_futex_ipc, 0);
/*TODO:处理锁信息*/
uaddr = (uint32_t *)(msg->msg_buf[0]);
futex_op = msg->msg_buf[1];
val = msg->msg_buf[2];
timeout = (const struct timespec *)(msg->msg_buf[3]); /*or val2*/
uaddr2 = msg->msg_buf[4];
val3 = msg->msg_buf[5];
futex_op = futex_op & 0x7f;
switch (futex_op)
{
case FUTEX_REQUEUE:
{
if (val3 == *uaddr)
{
futex_lock_t *flt = futex_find(&ft, uaddr);
int rel_cnt = 0;
int wake_cnt = 0;
if (flt)
{
wake_cnt = val = INT_MAX ? fq_queue_len(&flt->fqt) : val;
for (int i = 0; i < wake_cnt; i++)
{
obj_handler_t hd;
int ret = fq_dequeue(&flt->fqt, &hd);
if (ret != 0)
{
continue;
}
if (fq_queue_len(&flt->fqt) == 0)
{
flt->uaddr = 0;
}
/*TODO: ipc_send()*/
}
}
}
}
break;
}
ipc_reply(hd_futex_ipc, msg_tag_init4(0, 0, 0, 0));
}
@@ -135,7 +188,9 @@ int be_futex(uint32_t *uaddr, int futex_op, uint32_t val,
total = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000 / 1000;
}
umword_t st_val;
ipc_msg_t *msg = (ipc_msg_t *)futex_thread_msg_bug;
ipc_msg_t *msg;
thread_msg_buf_get(-1, (umword_t *)(&msg), NULL);
msg->msg_buf[0] = (umword_t)uaddr;
msg->msg_buf[1] = (umword_t)futex_op;

View File

@@ -51,6 +51,7 @@ msg_tag_t ipc_bind(obj_handler_t obj, obj_handler_t tag_th, umword_t user_obj);
msg_tag_t ipc_wait(obj_handler_t obj, umword_t *user_obj);
msg_tag_t ipc_reply(obj_handler_t obj, msg_tag_t tag);
msg_tag_t ipc_call(obj_handler_t obj, msg_tag_t in_tag, ipc_timeout_t timeout);
msg_tag_t ipc_send(obj_handler_t obj, msg_tag_t in_tag, ipc_timeout_t timeout);
#define EWTIMEDOUT 131 /* Connection timed out */
#define ERTIMEDOUT 132 /* Connection timed out */
#define EWTIMEDOUT 131 /* Connection timed out */
#define ERTIMEDOUT 132 /* Connection timed out */

View File

@@ -11,18 +11,19 @@ enum ipc_op
IPC_REPLY, //!< 服务端回复信息
IPC_BIND, //!< 绑定服务端线程
IPC_UNBIND, //!< 解除绑定
IPC_SEND, //!< 发送数据
};
msg_tag_t ipc_bind(obj_handler_t obj, obj_handler_t tag_th, umword_t user_obj)
{
register volatile umword_t r0 asm("r0");
mk_syscall(syscall_prot_create(IPC_BIND, IPC_PROT, obj).raw,
0,
tag_th,
user_obj,
0,
0,
0);
0,
tag_th,
user_obj,
0,
0,
0);
asm __volatile__(""
:
:
@@ -37,12 +38,12 @@ msg_tag_t ipc_wait(obj_handler_t obj, umword_t *user_obj)
register volatile umword_t r1 asm("r1");
mk_syscall(syscall_prot_create(IPC_WAIT, IPC_PROT, obj).raw,
0,
0,
0,
0,
0,
0);
0,
0,
0,
0,
0,
0);
asm __volatile__(""
:
:
@@ -58,12 +59,12 @@ msg_tag_t ipc_reply(obj_handler_t obj, msg_tag_t in_tag)
register volatile umword_t r0 asm("r0");
mk_syscall(syscall_prot_create(IPC_REPLY, IPC_PROT, obj).raw,
in_tag.raw,
0,
0,
0,
0,
0);
in_tag.raw,
0,
0,
0,
0,
0);
asm __volatile__(""
:
:
@@ -77,12 +78,12 @@ msg_tag_t ipc_call(obj_handler_t obj, msg_tag_t in_tag, ipc_timeout_t timeout)
register volatile umword_t r0 asm("r0");
mk_syscall(syscall_prot_create(IPC_CALL, IPC_PROT, obj).raw,
in_tag.raw,
timeout.raw,
0,
0,
0,
0);
in_tag.raw,
timeout.raw,
0,
0,
0,
0);
asm __volatile__(""
:
:
@@ -90,4 +91,23 @@ msg_tag_t ipc_call(obj_handler_t obj, msg_tag_t in_tag, ipc_timeout_t timeout)
msg_tag_t tag = msg_tag_init(r0);
return tag;
}
}
msg_tag_t ipc_send(obj_handler_t obj, msg_tag_t in_tag, ipc_timeout_t timeout)
{
register volatile umword_t r0 asm("r0");
mk_syscall(syscall_prot_create(IPC_SEND, IPC_PROT, obj).raw,
in_tag.raw,
timeout.raw,
0,
0,
0,
0);
asm __volatile__(""
:
:
: "r0");
msg_tag_t tag = msg_tag_init(r0);
return tag;
}

View File

@@ -24,5 +24,5 @@ void u_sleep_init(void)
void u_sleep_ms(size_t ms)
{
ipc_call(hd, msg_tag_init4(0, 0, 0, 0), ipc_timeout_create2(ms / (1000 / SYS_SCHE_HZ), 0));
ipc_send(hd, msg_tag_init4(0, 0, 0, 0), ipc_timeout_create2(ms / (1000 / SYS_SCHE_HZ), 0));
}

View File

@@ -21,8 +21,6 @@
extern void futex_init(void);
int main(int argc, char *args[])
{
fs_backend_init();
// futex_init();
ulog_write_str(LOG_PROT, "init..\n");
#if 0
ulog_test();
@@ -35,9 +33,9 @@ int main(int argc, char *args[])
mm_test();
app_test();
mpu_test();
ipc_test();
thread_press_test();
kobj_create_press_test();
ipc_test();
#endif
uenv_t env = *u_get_global_env();
obj_handler_t ipc_hd;

View File

@@ -98,6 +98,7 @@ static void thread_test_func2(void)
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));
printf("th2:%s", buf);
// hard_sleep();
}
printf("thread_test_func2.\n");
task_unmap(TASK_PROT, vpage_create_raw3(KOBJ_DELETE_RIGHT, 0, th2_hd));
@@ -108,12 +109,14 @@ static void thread_test_func3(void)
{
char *buf;
umword_t len;
thread_msg_buf_get(th3_hd, (umword_t *)(&buf), NULL);
thread_msg_buf_get(th3_hd, (umword_t *)(&buf), &len);
memset(buf, 0, len);
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));
printf("th3:%s", buf);
// hard_sleep();
}
printf("thread_test_func2.\n");
task_unmap(TASK_PROT, vpage_create_raw3(KOBJ_DELETE_RIGHT, 0, th3_hd));