fix: The timer sequence stuck in infinite loop after series of delete operation
authorMinep <zelong56@gmail.com>
Sat, 11 Jun 2022 23:25:28 +0000 (00:25 +0100)
committerMinep <zelong56@gmail.com>
Sat, 11 Jun 2022 23:25:28 +0000 (00:25 +0100)
fix: To mitigate race condition, make the system call mask interrupt by default, and unmask when and only when needed.
improve: better debugging experience when GP happened due to the buggy iret!

lunaix-os/bx_enh_dbg.ini
lunaix-os/includes/lunaix/ds/llist.h
lunaix-os/kernel/asm/x86/idt.c
lunaix-os/kernel/asm/x86/interrupt.S
lunaix-os/kernel/asm/x86/intr_routines.c
lunaix-os/kernel/lxinit.c
lunaix-os/kernel/sched.c

index c9f2bf5df6067145700ca50595904e8e09de5d51..5e8e29861dce8a23a631f0bd535b8f779acf0228 100644 (file)
@@ -19,8 +19,8 @@ isLittleEndian = TRUE
 DefaultAsmLines = 512
 DumpWSIndex = 2
 DockOrder = 0x123
 DefaultAsmLines = 512
 DumpWSIndex = 2
 DockOrder = 0x123
-ListWidthPix[0] = 485
-ListWidthPix[1] = 667
-ListWidthPix[2] = 764
-MainWindow = 0, 0, 1283, 500
+ListWidthPix[0] = 257
+ListWidthPix[1] = 318
+ListWidthPix[2] = 367
+MainWindow = 0, 0, 743, 500
 FontName = Normal
 FontName = Normal
index dd2a1921b97bc07b5114413c7abac919ab0d3870..79fa99173003797fe8dfa6f0a805576a4d506151 100644 (file)
@@ -1,12 +1,13 @@
 /**
  * @file llist.h
  * @author Lunaixsky
 /**
  * @file llist.h
  * @author Lunaixsky
- * @brief This doubly linked cyclic list is adopted from Linux kernel <linux/list.h>
+ * @brief This doubly linked cyclic list is adopted from Linux kernel
+ * <linux/list.h>
  * @version 0.1
  * @date 2022-03-12
  * @version 0.1
  * @date 2022-03-12
- * 
+ *
  * @copyright Copyright (c) 2022
  * @copyright Copyright (c) 2022
- * 
+ *
  */
 #ifndef __LUNAIX_LLIST_H
 #define __LUNAIX_LLIST_H
  */
 #ifndef __LUNAIX_LLIST_H
 #define __LUNAIX_LLIST_H
@@ -31,7 +32,8 @@ __llist_add(struct llist_header* elem,
 }
 
 static inline void
 }
 
 static inline void
-llist_init_head(struct llist_header* head) {
+llist_init_head(struct llist_header* head)
+{
     head->next = head;
     head->prev = head;
 }
     head->next = head;
     head->prev = head;
 }
@@ -49,16 +51,19 @@ llist_prepend(struct llist_header* head, struct llist_header* elem)
 }
 
 static inline void
 }
 
 static inline void
-llist_delete(struct llist_header* elem) {
+llist_delete(struct llist_header* elem)
+{
     elem->prev->next = elem->next;
     elem->prev->next = elem->next;
-    elem->next->prev = elem->next;
-    
+    elem->next->prev = elem->prev;
+
     // make elem orphaned
     // make elem orphaned
-    elem->prev = elem;
-    elem->next = elem;
+    // elem->prev = elem;
+    // elem->next = elem;
 }
 
 }
 
-static inline int llist_empty(struct llist_header* elem) {
+static inline int
+llist_empty(struct llist_header* elem)
+{
     return elem->next == elem;
 }
 
     return elem->next == elem;
 }
 
@@ -68,8 +73,7 @@ static inline int llist_empty(struct llist_header* elem) {
  * @type:      the type of the struct this is embedded in.
  * @member:    the name of the list_struct within the struct.
  */
  * @type:      the type of the struct this is embedded in.
  * @member:    the name of the list_struct within the struct.
  */
-#define list_entry(ptr, type, member) \
-       container_of(ptr, type, member)
+#define list_entry(ptr, type, member) container_of(ptr, type, member)
 
 /**
  * list_for_each_entry -       iterate over list of given type
 
 /**
  * list_for_each_entry -       iterate over list of given type
@@ -77,10 +81,10 @@ static inline int llist_empty(struct llist_header* elem) {
  * @head:      the head for your list.
  * @member:    the name of the list_struct within the struct.
  */
  * @head:      the head for your list.
  * @member:    the name of the list_struct within the struct.
  */
-#define llist_for_each(pos, n, head, member)                               \
-       for (pos = list_entry((head)->next, typeof(*pos), member),      \
-               n = list_entry(pos->member.next, typeof(*pos), member); \
-            &pos->member != (head);                                                \
-            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+#define llist_for_each(pos, n, head, member)                                   \
+    for (pos = list_entry((head)->next, typeof(*pos), member),                 \
+        n = list_entry(pos->member.next, typeof(*pos), member);                \
+         &pos->member != (head);                                               \
+         pos = n, n = list_entry(n->member.next, typeof(*n), member))
 
 #endif /* __LUNAIX_LLIST_H */
 
 #endif /* __LUNAIX_LLIST_H */
index 6c7246cc9923ecdc7f83d3616f51c53f20104a5c..f453313ccd9fbf13f83b7a38b528ab9ee43b79f9 100644 (file)
@@ -7,24 +7,40 @@
 uint64_t _idt[IDT_ENTRY];
 uint16_t _idt_limit = sizeof(_idt) - 1;
 
 uint64_t _idt[IDT_ENTRY];
 uint16_t _idt_limit = sizeof(_idt) - 1;
 
-static inline void _set_idt_entry(uint32_t vector, uint16_t seg_selector, void (*isr)(), uint8_t dpl, uint8_t type) {
+static inline void
+_set_idt_entry(uint32_t vector,
+               uint16_t seg_selector,
+               void (*isr)(),
+               uint8_t dpl,
+               uint8_t type)
+{
     uintptr_t offset = (uintptr_t)isr;
     _idt[vector] = (offset & 0xffff0000) | IDT_ATTR(dpl, type);
     _idt[vector] <<= 32;
     _idt[vector] |= (seg_selector << 16) | (offset & 0x0000ffff);
 }
 
     uintptr_t offset = (uintptr_t)isr;
     _idt[vector] = (offset & 0xffff0000) | IDT_ATTR(dpl, type);
     _idt[vector] <<= 32;
     _idt[vector] |= (seg_selector << 16) | (offset & 0x0000ffff);
 }
 
-void _set_idt_intr_entry(uint32_t vector, uint16_t seg_selector, void (*isr)(), uint8_t dpl) {
+void
+_set_idt_intr_entry(uint32_t vector,
+                    uint16_t seg_selector,
+                    void (*isr)(),
+                    uint8_t dpl)
+{
     _set_idt_entry(vector, seg_selector, isr, dpl, IDT_INTERRUPT);
 }
 
     _set_idt_entry(vector, seg_selector, isr, dpl, IDT_INTERRUPT);
 }
 
-void _set_idt_trap_entry(uint32_t vector, uint16_t seg_selector, void (*isr)(), uint8_t dpl) {
+void
+_set_idt_trap_entry(uint32_t vector,
+                    uint16_t seg_selector,
+                    void (*isr)(),
+                    uint8_t dpl)
+{
     _set_idt_entry(vector, seg_selector, isr, dpl, IDT_TRAP);
 }
 
     _set_idt_entry(vector, seg_selector, isr, dpl, IDT_TRAP);
 }
 
-
 void
 void
-_init_idt() {
+_init_idt()
+{
     // CPU defined interrupts
     _set_idt_intr_entry(FAULT_DIVISION_ERROR, 0x08, _asm_isr0, 0);
     _set_idt_intr_entry(FAULT_GENERAL_PROTECTION, 0x08, _asm_isr13, 0);
     // CPU defined interrupts
     _set_idt_intr_entry(FAULT_DIVISION_ERROR, 0x08, _asm_isr0, 0);
     _set_idt_intr_entry(FAULT_GENERAL_PROTECTION, 0x08, _asm_isr13, 0);
@@ -32,17 +48,21 @@ _init_idt() {
 
     _set_idt_intr_entry(APIC_ERROR_IV, 0x08, _asm_isr250, 0);
     _set_idt_intr_entry(APIC_LINT0_IV, 0x08, _asm_isr251, 0);
 
     _set_idt_intr_entry(APIC_ERROR_IV, 0x08, _asm_isr250, 0);
     _set_idt_intr_entry(APIC_LINT0_IV, 0x08, _asm_isr251, 0);
-    _set_idt_intr_entry(APIC_SPIV_IV,  0x08, _asm_isr252, 0);
+    _set_idt_intr_entry(APIC_SPIV_IV, 0x08, _asm_isr252, 0);
     _set_idt_intr_entry(APIC_TIMER_IV, 0x08, _asm_isr253, 0);
     _set_idt_intr_entry(APIC_TIMER_IV, 0x08, _asm_isr253, 0);
-    _set_idt_intr_entry(PC_KBD_IV,  0x08, _asm_isr201, 0);
+    _set_idt_intr_entry(PC_KBD_IV, 0x08, _asm_isr201, 0);
 
 
-    _set_idt_intr_entry(RTC_TIMER_IV,  0x08, _asm_isr210, 0);
+    _set_idt_intr_entry(RTC_TIMER_IV, 0x08, _asm_isr210, 0);
 
     // system defined interrupts
     _set_idt_intr_entry(LUNAIX_SYS_PANIC, 0x08, _asm_isr32, 0);
 
 
     // system defined interrupts
     _set_idt_intr_entry(LUNAIX_SYS_PANIC, 0x08, _asm_isr32, 0);
 
-    // syscall is a trap gate (recall: trap does NOT clear IF flag upon interruption)
-    // XXX: this should be fine, as our design of context switch support interruptible syscall
-    // FIXME: This may cause nasty concurrency bug! We should 'lockify' our code!
-    _set_idt_trap_entry(LUNAIX_SYS_CALL, 0x08, _asm_isr33, 3);
+    // syscall is a trap gate (recall: trap does NOT clear IF flag upon
+    // interruption)
+    // // XXX: this should be fine, as our design of context switch support
+    // interruptible syscall We make this a non-trap entry, and enable interrupt
+    // only when needed!
+    // FIXME: This may cause nasty concurrency bug! We should 'lockify' our
+    // code!
+    _set_idt_intr_entry(LUNAIX_SYS_CALL, 0x08, _asm_isr33, 3);
 }
\ No newline at end of file
 }
\ No newline at end of file
index 4647e95a467da053aec06509b5612b149bd3698d..e0cda172957dc1e7efc253cd55cc31df224b89b0 100644 (file)
@@ -1,7 +1,7 @@
 #define __ASM__
 #include <arch/x86/interrupts.h>
 #include <lunaix/common.h>
 #define __ASM__
 #include <arch/x86/interrupts.h>
 #include <lunaix/common.h>
-// #define __ASM_INTR_DIAGNOSIS
+#define __ASM_INTR_DIAGNOSIS
 
 .macro isr_template vector, no_error_code=1
     .global _asm_isr\vector
 
 .macro isr_template vector, no_error_code=1
     .global _asm_isr\vector
         addl $8, %esp
 
 #ifdef __ASM_INTR_DIAGNOSIS
         addl $8, %esp
 
 #ifdef __ASM_INTR_DIAGNOSIS
-        cmpl $0, (%esp)
-        jz 1f
-        iret
-1:
-        movl $__current, %eax
-        movl  (%esp), %ebx
-        movl $debug_resv, %ecx
-        ud2
-#else
-        iret
+        pushl %eax
+        movl 4(%esp), %eax
+        movl %eax, debug_resv
+        popl %eax
 #endif
 #endif
+        iret
index f68b2ceeb80dec144b6b624f2a1a6809453c2b0d..0b05e751554245e2c19be72252a8035e99ff426e 100644 (file)
@@ -1,7 +1,8 @@
 #include <arch/x86/interrupts.h>
 #include <arch/x86/interrupts.h>
-#include <lunaix/tty/tty.h>
+#include <lunaix/process.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
+#include <lunaix/tty/tty.h>
 
 #include <klibc/stdio.h>
 
 
 #include <klibc/stdio.h>
 
 LOG_MODULE("INTR")
 
 extern void
 LOG_MODULE("INTR")
 
 extern void
-intr_routine_page_fault (const isr_param* param);
+intr_routine_page_fault(const isr_param* param);
+
+extern uint32_t debug_resv;
 
 
-void 
-__print_panic_msg(const char* msg, const isr_param* param) 
+void
+__print_panic_msg(const char* msg, const isr_param* param)
 {
     kprint_panic("  INT %u: (%x) [%p: %p] %s",
 {
     kprint_panic("  INT %u: (%x) [%p: %p] %s",
-            param->vector,
-            param->err_code,
-            param->cs,
-            param->eip,
-            msg);
+                 param->vector,
+                 param->err_code,
+                 param->cs,
+                 param->eip,
+                 msg);
 }
 
 void
 }
 
 void
-intr_routine_divide_zero (const isr_param* param) 
+intr_routine_divide_zero(const isr_param* param)
 {
     __print_panic_msg("Divide by zero!", param);
     spin();
 }
 
 void
 {
     __print_panic_msg("Divide by zero!", param);
     spin();
 }
 
 void
-intr_routine_general_protection (const isr_param* param) 
+intr_routine_general_protection(const isr_param* param)
 {
 {
+    kprintf(KERROR "Addr: %p\n", (&debug_resv)[0]);
+    kprintf(KERROR "Expected: %p\n", __current->intr_ctx.eip);
     __print_panic_msg("General Protection", param);
     spin();
 }
 
 void
     __print_panic_msg("General Protection", param);
     spin();
 }
 
 void
-intr_routine_sys_panic (const isr_param* param) 
+intr_routine_sys_panic(const isr_param* param)
 {
     __print_panic_msg((char*)(param->registers.edi), param);
     spin();
 }
 
 void
 {
     __print_panic_msg((char*)(param->registers.edi), param);
     spin();
 }
 
 void
-intr_routine_fallback (const isr_param* param) 
+intr_routine_fallback(const isr_param* param)
 {
     __print_panic_msg("Unknown Interrupt", param);
     spin();
 {
     __print_panic_msg("Unknown Interrupt", param);
     spin();
@@ -53,17 +58,17 @@ intr_routine_fallback (const isr_param* param)
 
 /**
  * @brief ISR for Spurious interrupt
 
 /**
  * @brief ISR for Spurious interrupt
- * 
+ *
  * @param isr_param passed by CPU
  */
 void
  * @param isr_param passed by CPU
  */
 void
-intr_routine_apic_spi (const isr_param* param)
+intr_routine_apic_spi(const isr_param* param)
 {
     // FUTURE: do nothing for now
 }
 
 {
     // FUTURE: do nothing for now
 }
 
-void 
-intr_routine_apic_error (const isr_param* param)
+void
+intr_routine_apic_error(const isr_param* param)
 {
     uint32_t error_reg = apic_read_reg(APIC_ESR);
     char buf[32];
 {
     uint32_t error_reg = apic_read_reg(APIC_ESR);
     char buf[32];
@@ -73,14 +78,14 @@ intr_routine_apic_error (const isr_param* param)
 }
 
 void
 }
 
 void
-intr_routine_init() 
+intr_routine_init()
 {
 {
-    intr_subscribe(FAULT_DIVISION_ERROR,     intr_routine_divide_zero);
+    intr_subscribe(FAULT_DIVISION_ERROR, intr_routine_divide_zero);
     intr_subscribe(FAULT_GENERAL_PROTECTION, intr_routine_general_protection);
     intr_subscribe(FAULT_GENERAL_PROTECTION, intr_routine_general_protection);
-    intr_subscribe(FAULT_PAGE_FAULT,         intr_routine_page_fault);
-    intr_subscribe(LUNAIX_SYS_PANIC,         intr_routine_sys_panic);
-    intr_subscribe(APIC_SPIV_IV,             intr_routine_apic_spi);
-    intr_subscribe(APIC_ERROR_IV,            intr_routine_apic_error);
+    intr_subscribe(FAULT_PAGE_FAULT, intr_routine_page_fault);
+    intr_subscribe(LUNAIX_SYS_PANIC, intr_routine_sys_panic);
+    intr_subscribe(APIC_SPIV_IV, intr_routine_apic_spi);
+    intr_subscribe(APIC_ERROR_IV, intr_routine_apic_error);
 
     intr_set_fallback_handler(intr_set_fallback_handler);
 }
\ No newline at end of file
 
     intr_set_fallback_handler(intr_set_fallback_handler);
 }
\ No newline at end of file
index f7b0f955973d158d302365aed186ce6ce522ec83..fa8458c98eca67c28e782f9a3a7948ea32d283e9 100644 (file)
@@ -15,7 +15,7 @@ extern uint8_t __kernel_start;
 LOG_MODULE("INIT")
 
 // #define FORK_BOMB_DEMO
 LOG_MODULE("INIT")
 
 // #define FORK_BOMB_DEMO
-#define WAIT_DEMO
+// #define WAIT_DEMO
 
 void
 _lxinit_main()
 
 void
 _lxinit_main()
@@ -48,20 +48,16 @@ _lxinit_main()
 
     pid_t p = 0;
 
 
     pid_t p = 0;
 
-    if (!(p = fork())) {
+    if (!fork()) {
         kprintf("Test no hang!");
         kprintf("Test no hang!");
-        sleep(1);
+        sleep(12);
         _exit(0);
     }
 
         _exit(0);
     }
 
-    waitpid(-1, &status, 0);
-    // FIXME: WNOHANG还有点问题……
-    // waitpid(-1, &status, WNOHANG);
-
-    sleep(2);
+    waitpid(-1, &status, WNOHANG);
 
     // 这里是就是LunaixOS的第一个进程了!
 
     // 这里是就是LunaixOS的第一个进程了!
-    for (size_t i = 0; i < 10; i++) {
+    for (size_t i = 0; i < 5; i++) {
         pid_t pid = 0;
         if (!(pid = fork())) {
             sleep(i);
         pid_t pid = 0;
         if (!(pid = fork())) {
             sleep(i);
index 35e3cff5c69f2a6164a40009cc48d560eb3e1bc5..442921ebccfb444fd13d1374988f5fdbe7cef108 100644 (file)
@@ -70,6 +70,8 @@ schedule()
         return;
     }
 
         return;
     }
 
+    // 上下文切换相当的敏感!我们不希望任何的中断打乱栈的顺序……
+    cpu_disable_interrupt();
     struct proc_info* next;
     int prev_ptr = sched_ctx.procs_index;
     int ptr = prev_ptr;
     struct proc_info* next;
     int prev_ptr = sched_ctx.procs_index;
     int ptr = prev_ptr;
@@ -81,8 +83,6 @@ schedule()
 
     sched_ctx.procs_index = ptr;
 
 
     sched_ctx.procs_index = ptr;
 
-    // 上下文切换相当的敏感!我们不希望任何的中断打乱栈的顺序……
-    cpu_disable_interrupt();
     run(next);
 }
 
     run(next);
 }
 
@@ -99,6 +99,7 @@ __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
     if (!seconds) {
         return 0;
     }
     if (!seconds) {
         return 0;
     }
+
     if (__current->timer) {
         return __current->timer->counter / timer_context()->running_frequency;
     }
     if (__current->timer) {
         return __current->timer->counter / timer_context()->running_frequency;
     }
@@ -118,7 +119,7 @@ __DEFINE_LXSYSCALL1(void, exit, int, status)
 
 __DEFINE_LXSYSCALL(void, yield)
 {
 
 __DEFINE_LXSYSCALL(void, yield)
 {
-    sched_yield();
+    schedule();
 }
 
 pid_t
 }
 
 pid_t
@@ -143,6 +144,8 @@ _wait(pid_t wpid, int* status, int options)
     if (llist_empty(&__current->children)) {
         return -1;
     }
     if (llist_empty(&__current->children)) {
         return -1;
     }
+
+    cpu_enable_interrupt();
 repeat:
     llist_for_each(proc, n, &__current->children, siblings)
     {
 repeat:
     llist_for_each(proc, n, &__current->children, siblings)
     {
@@ -165,6 +168,7 @@ repeat:
     goto repeat;
 
 done:
     goto repeat;
 
 done:
+    cpu_disable_interrupt();
     *status = (proc->exit_code & 0xffff) | status_flags;
     return destroy_process(proc->pid);
 }
     *status = (proc->exit_code & 0xffff) | status_flags;
     return destroy_process(proc->pid);
 }