diff --git a/Ubiquitous/XiZi_AIoT/services/app/simple_server.c b/Ubiquitous/XiZi_AIoT/services/app/simple_server.c index 2ae2d9e12..e6eafe275 100755 --- a/Ubiquitous/XiZi_AIoT/services/app/simple_server.c +++ b/Ubiquitous/XiZi_AIoT/services/app/simple_server.c @@ -30,7 +30,8 @@ int IPC_DO_SERVE_FUNC(Ipc_hello_string)(char* buf, int* len) return 0; } -IPC_SERVER_INTERFACE(Ipc_add, 2); +// IPC_SERVER_INTERFACE(Ipc_add, 2); +IPC_SERVER_THREAD_INTERFACE(Ipc_add, 2); IPC_SERVER_INTERFACE(Ipc_hello_string, 2); IPC_SERVER_REGISTER_INTERFACES(IpcSimpleServer, 2, Ipc_hello_string, Ipc_add); diff --git a/Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c b/Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c index c7836afa9..49ef9eccc 100644 --- a/Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c +++ b/Ubiquitous/XiZi_AIoT/services/app/test_irq_handler.c @@ -23,18 +23,18 @@ int IPC_DO_SERVE_FUNC(Ipc_intr_3)(void* ignore) int IPC_DO_SERVE_FUNC(Ipc_wait_intr_3)(void* ignore) { // delay the this handle - if (!has_one_interrupt) { - delay_session(); - return -1; + while (!has_one_interrupt) { + yield(SYS_TASK_YIELD_NO_REASON); } // serve can be done by now has_one_interrupt = false; + return 0; } IPC_SERVER_INTERFACE(Ipc_intr_3, 1); -IPC_SERVER_INTERFACE(Ipc_wait_intr_3, 1); +IPC_SERVER_THREAD_INTERFACE(Ipc_wait_intr_3, 1); IPC_SERVER_REGISTER_INTERFACES(IpcSwIntrHandler, 2, Ipc_intr_3, Ipc_wait_intr_3); int main() { diff --git a/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c b/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c index 7fdb4506d..2f0f3b95f 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c +++ b/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.c @@ -168,25 +168,6 @@ int cur_session_id(void) return cur_sess_id; } -static bool session_delayed = false; -void delay_session(void) -{ - session_delayed = true; -} - -bool is_cur_session_delayed(void) -{ - return session_delayed; -} - -bool is_cur_handler_been_delayed() -{ - if (ipc_server_loop_cur_msg == NULL) { - return false; - } - return ipc_server_loop_cur_msg->header.delayed == 1; -} - void ipc_server_loop(struct IpcNode* ipc_node) { struct Session session_list[NR_MAX_SESSION]; @@ -199,49 +180,82 @@ void ipc_server_loop(struct IpcNode* ipc_node) */ poll_session(session_list, NR_MAX_SESSION); /* handle each session */ - bool has_delayed = true; - for (int repeat = 0; repeat <= 1 && has_delayed; repeat++) { - has_delayed = false; - for (int i = 0; i < NR_MAX_SESSION; i++) { - session_delayed = false; - if (session_list[i].buf == NULL) { - yield(SYS_TASK_YIELD_NO_REASON); + 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; + ipc_server_loop_cur_msg = IPCSESSION_MSG(&session_list[i]); + if (ipc_server_loop_cur_msg->header.magic == IPC_MSG_MAGIC && ipc_server_loop_cur_msg->header.valid == 1 && // + ipc_server_loop_cur_msg->header.done == 1) { + session_forward_head(&session_list[i], ipc_server_loop_cur_msg->header.len); + ipc_server_loop_cur_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 (ipc_server_loop_cur_msg->header.magic == IPC_MSG_MAGIC && ipc_server_loop_cur_msg->header.valid == 1 && // + ipc_server_loop_cur_msg->header.handling == 0 && ipc_server_loop_cur_msg->header.done == 0) { + if (session_used_size(&session_list[i]) == 0 && session_forward_tail(&session_list[i], ipc_server_loop_cur_msg->header.len) < 0) { break; } - cur_sess_id = session_list[i].id; - ipc_server_loop_cur_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 (ipc_server_loop_cur_msg->header.magic == IPC_MSG_MAGIC && ipc_server_loop_cur_msg->header.valid == 1 && ipc_server_loop_cur_msg->header.done == 0) { - if (session_used_size(&session_list[i]) == 0 && session_forward_tail(&session_list[i], ipc_server_loop_cur_msg->header.len) < 0) { - break; - } - // this is a message needs to handle - if (ipc_node->interfaces[ipc_server_loop_cur_msg->header.opcode]) { - ipc_node->interfaces[ipc_server_loop_cur_msg->header.opcode](ipc_server_loop_cur_msg); - // check if this session is delayed by op handler, all messages after the delayed message in current session is blocked. - if (ipc_server_loop_cur_msg->header.done == 0) { - ipc_server_loop_cur_msg->header.delayed = 1; - has_delayed = true; - break; - } - } else { - printf("Unsupport opcode(%u) for server: %s\n", ipc_server_loop_cur_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], ipc_server_loop_cur_msg->header.len) < 0) { - break; - } - ipc_server_loop_cur_msg = IPCSESSION_MSG(&session_list[i]); + // this is a message needs to handle + if (ipc_node->interfaces[ipc_server_loop_cur_msg->header.opcode]) { + ipc_node->interfaces[ipc_server_loop_cur_msg->header.opcode](ipc_server_loop_cur_msg); + } else { + printf("Unsupport opcode(%u) for server: %s\n", ipc_server_loop_cur_msg->header.opcode, ipc_node->name); } - // stop handle this session - cur_sess_id = -1; - ipc_server_loop_cur_msg = NULL; + // current msg is a message that needs to ignore + // finish this message in server's perspective + if (ipc_server_loop_cur_msg->header.done == 0) { + break; + } + session_forward_head(&session_list[i], ipc_server_loop_cur_msg->header.len); + ipc_server_loop_cur_msg = IPCSESSION_MSG(&session_list[i]); } + // stop handle this session + cur_sess_id = -1; + ipc_server_loop_cur_msg = NULL; } } +} + +// utils +void _ipc_addr_to_buf(uintptr_t addr, char buf[17]) +{ + int buf_idx = 0; + while (addr != 0) { + int x = addr % 16; + if (x < 10) { + buf[buf_idx] = x + '0'; + } else { + buf[buf_idx] = x - 10 + 'A'; + } + buf_idx++; + addr /= 16; + } + buf[buf_idx] = '\0'; +} + +uintptr_t _ipc_buf_to_addr(char* buf) +{ + uintptr_t addr = 0; + int buf_idx = 0; + uintptr_t multiplier = 1; + while (buf_idx < 17 && buf[buf_idx] != '\0') { + uint8_t x = (uint8_t)buf[buf_idx]; + if (x >= '0' && x <= '9') { + x -= '0'; + } else if (x >= 'A' && x <= 'F') { + x -= 'A'; + x += 10; + } + addr += (uintptr_t)x * multiplier; + multiplier *= 16; + buf_idx++; + } + return addr; } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.h b/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.h index a10016b48..82af08799 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.h +++ b/Ubiquitous/XiZi_AIoT/services/lib/ipc/libipc.h @@ -33,6 +33,7 @@ Modification: #include #include #include +#include #include "ipcargs.h" #include "session.h" @@ -47,7 +48,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 delayed : 1; + uint64_t handling : 1; uint64_t nr_args : 4; uint64_t opcode : 8; uint64_t len : 16; @@ -191,6 +192,7 @@ void ipc_server_loop(struct IpcNode* ipc_node); #define IPC_CALL(ipc_name) ipc_call_copy_args_##ipc_name #define IPC_SERVE(ipc_name) ipc_serve_##ipc_name +#define IPC_THREAD_SERVE(ipc_name) ipc_thread_serve_##ipc_name #define IPC_DO_SERVE_FUNC(ipc_name) ipc_do_serve_##ipc_name /// when defining a ipc server: @@ -236,7 +238,6 @@ 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) \ { \ @@ -245,16 +246,43 @@ bool is_cur_session_delayed(void); argv[i] = ipc_msg_get_nth_arg_buf(msg, i); \ } \ int32_t _ret = IPC_DO_SERVE##argc(ipc_name); \ - if (!is_cur_session_delayed()) { \ - ipc_msg_set_return(msg, &_ret); \ - msg->header.done = 1; \ - } \ + ipc_msg_set_return(msg, &_ret); \ + msg->header.done = 1; \ return 0; \ } -int cur_session_id(void); -/// @brief delay the session(message, or a inter-process-call) -/// the delayed call will be handled again later from begining, not from the position where delay_session() is called. -/// @param -void delay_session(void); -bool is_cur_handler_been_delayed(); \ No newline at end of file +void _ipc_addr_to_buf(uintptr_t addr, char buf[17]); +uintptr_t _ipc_buf_to_addr(char* buf); + +#define IPC_SERVER_THREAD_INTERFACE(ipc_name, argc) \ + static int IPC_THREAD_SERVE(ipc_name)(int ipc_argc, char** ipc_argv) \ + { \ + if (ipc_argc != 2) { \ + printf("[%s] Error server thread creation.\n", __func__); \ + exit(1); \ + return -1; \ + } \ + struct IpcMsg* msg = (struct IpcMsg*)_ipc_buf_to_addr(ipc_argv[1]); \ + void* argv[argc]; \ + for (int i = 0; i < argc; i++) { \ + 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; \ + exit(0); \ + return 0; \ + } \ + static int IPC_SERVE(ipc_name)(struct IpcMsg * msg) \ + { \ + char addr_buf[17]; \ + _ipc_addr_to_buf((uintptr_t)msg, addr_buf); \ + char* param[] = { #ipc_name, addr_buf, NULL }; \ + int tid = thread(IPC_THREAD_SERVE(ipc_name), #ipc_name, param); \ + if (tid > 0) { \ + msg->header.handling = 1; \ + } \ + return 0; \ + } + +int cur_session_id(void); \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/semaphore/semaphore_server.c b/Ubiquitous/XiZi_AIoT/services/semaphore/semaphore_server.c index a540ee0a1..a835ff8e9 100644 --- a/Ubiquitous/XiZi_AIoT/services/semaphore/semaphore_server.c +++ b/Ubiquitous/XiZi_AIoT/services/semaphore/semaphore_server.c @@ -63,15 +63,11 @@ int IPC_DO_SERVE_FUNC(Ipc_sem_wait)(sem_t* sem, int* timeout) /// @todo support timeout // return if sem is freed(no valid) or sem count is sufficient - if (!sem_pool[*sem].valid || sem_pool[*sem].count > 0) { - sem_pool[*sem].count--; - return SEMAPHORE_SUC; - } + while (sem_pool[*sem].valid && sem_pool[*sem].count <= 0) + ; - // delay current session - // this handler will be invoke again later - delay_session(); - return SEMAPHORE_ERR; + sem_pool[*sem].count--; + return SEMAPHORE_SUC; } int IPC_DO_SERVE_FUNC(Ipc_sem_signal)(sem_t* sem) @@ -91,7 +87,7 @@ int IPC_DO_SERVE_FUNC(Ipc_sem_signal)(sem_t* sem) IPC_SERVER_INTERFACE(Ipc_sem_create, 2); IPC_SERVER_INTERFACE(Ipc_sem_delete, 1); IPC_SERVER_INTERFACE(Ipc_sem_signal, 1); -IPC_SERVER_INTERFACE(Ipc_sem_wait, 2); +IPC_SERVER_THREAD_INTERFACE(Ipc_sem_wait, 2); IPC_SERVER_REGISTER_INTERFACES(IpcSemaphoreServer, 4, // Ipc_sem_create, Ipc_sem_delete, Ipc_sem_signal, Ipc_sem_wait); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/ipc.h b/Ubiquitous/XiZi_AIoT/softkernel/include/ipc.h index 775ee2bcb..4bed46666 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/ipc.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/ipc.h @@ -41,7 +41,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 delayed : 1; + uint64_t handling : 1; uint64_t nr_args : 4; uint64_t opcode : 8; uint64_t len : 16; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_poll_session.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_poll_session.c index 35cde916d..b1c751719 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_poll_session.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_poll_session.c @@ -39,7 +39,7 @@ Modification: static inline bool is_msg_needed(struct IpcMsg* msg) { assert(msg != NULL); - return msg->header.magic == IPC_MSG_MAGIC && msg->header.valid == 1 && msg->header.done == 0 && msg->header.delayed == 0; + return msg->header.magic == IPC_MSG_MAGIC && msg->header.valid == 1 && msg->header.done == 0 && msg->header.handling == 0; } int sys_poll_session(struct Session* userland_session_arr, int arr_capacity) diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/task.c b/Ubiquitous/XiZi_AIoT/softkernel/task/task.c index 4f9756e1d..bf8d7903d 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/task.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/task.c @@ -166,6 +166,10 @@ static void _dealloc_task_cb(struct Thread* task) bitmap64_free(&task->memspace->thread_stack_idx_bitmap, task->thread_context.user_stack_idx); /* thread's user stack space is also allocated for kernel free space */ assert(kfree((char*)task->thread_context.ustack_kvaddr)); + + if (task->memspace != NULL) { + task->memspace->mem_size -= USER_STACK_SIZE; + } } /* free thread's kernel stack */