Support blocking server.

This commit is contained in:
TXuian
2024-04-30 18:17:31 +08:00
parent 9f9e25a98e
commit 3a985252d9
13 changed files with 174 additions and 59 deletions
+40 -32
View File
@@ -156,6 +156,11 @@ void delay_session(void)
session_delayed = true;
}
bool is_cur_session_delayed(void)
{
return session_delayed;
}
void ipc_server_loop(struct IpcNode* ipc_node)
{
struct Session session_list[NR_MAX_SESSION];
@@ -168,43 +173,46 @@ void ipc_server_loop(struct IpcNode* ipc_node)
*/
poll_session(session_list, NR_MAX_SESSION);
/* handle each session */
for (int i = 0; i < NR_MAX_SESSION; i++) {
if (session_list[i].buf == NULL) {
yield(SYS_TASK_YIELD_NO_REASON);
break;
}
cur_sess_id = session_list[i].id;
struct IpcMsg* msg = IPCSESSION_MSG(&session_list[i]);
/* handle every message in current session
a session could be delay in case one of its message(current message) needs to wait for an interrupt message's arrival
interfaces[opcode] should explicitly call delay_session() and return to delay this session
*/
while (msg->header.magic == IPC_MSG_MAGIC && msg->header.valid == 1 && msg->header.done == 0) {
// printf("session %d [%d, %d]\n", session_list[i].id, session_list[i].head, session_list[i].tail);
if (session_used_size(&session_list[i]) == 0 && session_forward_tail(&session_list[i], msg->header.len) < 0) {
break;
for (int repeat = 0; repeat <= 1; repeat++) {
for (int i = 0; i < NR_MAX_SESSION; i++) {
if (session_list[i].buf == NULL) {
yield(SYS_TASK_YIELD_NO_REASON);
continue;
}
// this is a message needs to handle
if (ipc_node->interfaces[msg->header.opcode]) {
ipc_node->interfaces[msg->header.opcode](msg);
// check if this session is delayed by op handler, all messages after the delayed message in current session is blocked.
if (session_delayed) {
session_delayed = false;
cur_sess_id = session_list[i].id;
struct IpcMsg* msg = IPCSESSION_MSG(&session_list[i]);
/* handle every message in current session
a session could be delay in case one of its message(current message) needs to wait for an interrupt message's arrival
interfaces[opcode] should explicitly call delay_session() and return to delay this session
*/
while (msg->header.magic == IPC_MSG_MAGIC && msg->header.valid == 1 && msg->header.done == 0) {
// printf("session %d [%d, %d]\n", session_list[i].id, session_list[i].head, session_list[i].tail);
if (session_used_size(&session_list[i]) == 0 && session_forward_tail(&session_list[i], msg->header.len) < 0) {
break;
}
} else {
printf("Unsupport opcode(%d) for server: %s\n", msg->header.opcode, ipc_node->name);
// this is a message needs to handle
if (ipc_node->interfaces[msg->header.opcode]) {
ipc_node->interfaces[msg->header.opcode](msg);
// check if this session is delayed by op handler, all messages after the delayed message in current session is blocked.
if (is_cur_session_delayed()) {
msg->header.delayed = 1;
session_delayed = false;
break;
}
} else {
printf("Unsupport opcode(%d) for server: %s\n", msg->header.opcode, ipc_node->name);
}
// current msg is a message that needs to ignore
// finish this message in server's perspective
if (session_forward_head(&session_list[i], msg->header.len) < 0) {
break;
}
msg = IPCSESSION_MSG(&session_list[i]);
}
// current msg is a message that needs to ignore
// finish this message in server's perspective
if (session_forward_head(&session_list[i], msg->header.len) < 0) {
break;
}
msg = IPCSESSION_MSG(&session_list[i]);
// stop handle this session
cur_sess_id = -1;
}
// stop handle this session
cur_sess_id = -1;
}
}
}
@@ -47,7 +47,7 @@ typedef struct {
uint64_t valid : 1; // for server to peek new msg
uint64_t done : 1; // for client to check request done
uint64_t init : 1; // for client to check request done
uint64_t reserved : 1;
uint64_t delayed : 1;
uint64_t nr_args : 4;
uint64_t opcode : 8;
uint64_t len : 16;
@@ -225,6 +225,7 @@ void ipc_server_loop(struct IpcNode* ipc_node);
return res; \
}
bool is_cur_session_delayed(void);
#define IPC_SERVER_INTERFACE(ipc_name, argc) \
static int IPC_SERVE(ipc_name)(struct IpcMsg * msg) \
{ \
@@ -233,8 +234,10 @@ void ipc_server_loop(struct IpcNode* ipc_node);
argv[i] = ipc_msg_get_nth_arg_buf(msg, i); \
} \
int32_t _ret = IPC_DO_SERVE##argc(ipc_name); \
ipc_msg_set_return(msg, &_ret); \
msg->header.done = 1; \
if (!is_cur_session_delayed()) { \
ipc_msg_set_return(msg, &_ret); \
msg->header.done = 1; \
} \
return 0; \
}