Improve process/thread termination.
authorcoderain <coderain@sdf.org>
Sat, 8 Sep 2018 18:04:03 +0000 (20:04 +0200)
committercoderain <coderain@sdf.org>
Sat, 8 Sep 2018 18:04:03 +0000 (20:04 +0200)
kernel/include/process.h
kernel/src/exception.c
kernel/src/interrupt.c
kernel/src/process.c
kernel/src/thread.c

index d23a782a25b780f02238b3c691232cdc6e266e8d..c55205c48677f56d7e5ff7d783fcdadfd9e4626d 100644 (file)
@@ -79,6 +79,7 @@ void process_cleanup(object_t *proc);
 dword_t process_pre_wait(object_t *obj, void *parameter, wait_condition_t *condition);
 void destroy_process(process_t *process);
 process_t *switch_process(process_t *new_process);
+void terminate_process(process_t *proc, dword_t exit_code);
 void process_init(void);
 
 #endif
index 218d67b96e68667069f40bfae91201806266be05..bf84b2ac05d3c210ef529d77b29f150d87e17b9b 100644 (file)
@@ -59,9 +59,12 @@ static void raise_exception_internal(thread_t *thread, processor_mode_t mode, ex
         }
         else
         {
-            if (current) cpu_enable_interrupts();
-            terminate_thread_internal(thread, 1);
-            ASSERT(!current);
+
+            dword_t exit_code = 1; // TODO: Perhaps something more meaningful
+            process_t *proc = thread->owner_process;
+            reference(&proc->header);
+            terminate_process(proc, exit_code);
+            dereference(&proc->header);
         }
     }
     else
@@ -72,6 +75,7 @@ static void raise_exception_internal(thread_t *thread, processor_mode_t mode, ex
         if (thread->kernel_handler.eip)
         {
             thread->kernel_handler.eax = 1;
+            thread->in_kernel--;
             exception_return(thread->kernel_handler);
         }
         else
index 73ff34247b5d76ee2d13ed540a16112195f6c512..e7dce9f22182a23968f368f96e85d1b4658c9e97 100644 (file)
@@ -46,16 +46,12 @@ static void idt_main_handler(byte_t interrupt_num, registers_t regs)
     if (thread)
     {
         ASSERT(thread->in_kernel > 0);
+
         if (--thread->in_kernel == 0)
         {
             thread->last_context = NULL;
-
-            if (thread->terminated || (thread->frozen > 0))
-            {
-                cpu_enable_interrupts();
-                syscall_yield_quantum();
-            }
-
+            if (thread->terminating) thread->terminated = TRUE;
+            if (thread->terminated || thread->frozen > 0) syscall_yield_quantum();
             ASSERT(!thread->terminated && (thread->frozen <= 0));
         }
     }
index 0574281ab69e4c745cdc93fa96afc5d54969fc14..1305277ebf7c16ed84e355f1a5fe7b5e16591622 100644 (file)
@@ -86,6 +86,8 @@ void destroy_process(process_t *proc)
     lock_release(&proc->handle_table_lock);
 
     proc->terminated = TRUE;
+    syscall_clock_get_time(&proc->end_time);
+
     dereference(&proc->header);
 }
 
@@ -425,10 +427,26 @@ cleanup:
     return ret;
 }
 
+void terminate_process(process_t *proc, dword_t exit_code)
+{
+    proc->terminating = TRUE;
+    proc->exit_code = exit_code;
+
+    lock_acquire_shared(&proc->thread_list_lock);
+
+    list_entry_t *ptr;
+    for (ptr = proc->threads.next; ptr != &proc->threads; ptr = ptr->next)
+    {
+        thread_t *thread = CONTAINER_OF(ptr, thread_t, in_process_list);;
+        terminate_thread_internal(thread, exit_code);
+    }
+
+    lock_release(&proc->thread_list_lock);
+}
+
 sysret_t syscall_terminate(handle_t handle, dword_t exit_code)
 {
     process_t *proc;
-    thread_t *current_thread = get_current_thread();
 
     if (handle == INVALID_HANDLE)
     {
@@ -440,42 +458,9 @@ sysret_t syscall_terminate(handle_t handle, dword_t exit_code)
         if (!reference_by_handle(handle, OBJECT_PROCESS, (object_t**)&proc)) return ERR_INVALID;
     }
 
-    proc->terminating = TRUE;
-    proc->exit_code = exit_code;
-    syscall_clock_get_time(&proc->end_time);
-
-    lock_acquire_shared(&proc->thread_list_lock);
-
-    while (proc->threads.next != &proc->threads)
-    {
-        list_entry_t *ptr;
-        thread_t *thread = NULL;
-
-        for (ptr = proc->threads.next; ptr != &proc->threads; ptr = ptr->next)
-        {
-            thread = CONTAINER_OF(ptr, thread_t, in_process_list);
-            if (thread != current_thread) break;
-        }
-
-        if (ptr != &proc->threads)
-        {
-            lock_release(&proc->thread_list_lock);
-            terminate_thread_internal(thread, exit_code);
-            lock_acquire_shared(&proc->thread_list_lock);
-        }
-        else
-        {
-            break;
-        }
-    }
-
-    lock_release(&proc->thread_list_lock);
-
-    if (proc->threads.next == &proc->threads) destroy_process(proc);
+    terminate_process(proc, exit_code);
     dereference(&proc->header);
-
-    if (proc->threads.next == &proc->threads) return ERR_SUCCESS;
-    else return terminate_thread_internal(current_thread, exit_code);
+    return ERR_SUCCESS;
 }
 
 sysret_t syscall_query_process(handle_t handle, process_info_t info_type, void *buffer, dword_t size)
index f4b8c09433288b43d8743e41a40ad3f1f0c6747d..a3fa995c888249b554ad5efcfc43eef033856e43 100644 (file)
@@ -92,7 +92,7 @@ static inline bool_t is_thread_ready(thread_t *thread)
 {
     qword_t current_time = syscall_get_milliseconds();
 
-    if (thread->terminating || thread->terminated) return FALSE;
+    if (thread->terminated) return FALSE;
     if (thread->frozen > 0 && !thread->in_kernel) return FALSE;
     if (!thread->wait) return TRUE;
 
@@ -110,6 +110,13 @@ static inline bool_t is_thread_ready(thread_t *thread)
         return TRUE;
     }
 
+    if (thread->terminating)
+    {
+        thread->wait->result = WAIT_CANCELED;
+        thread->wait = NULL;
+        return TRUE;
+    }
+
     return FALSE;
 }
 
@@ -178,7 +185,6 @@ dword_t create_thread_internal(process_t *proc, thread_state_t *initial_state, d
     thread->exit_code = 0;
     thread->terminating = FALSE;
     thread->terminated = FALSE;
-    thread->in_kernel = 0;
     thread->last_context = NULL;
     thread->wait = NULL;
     memset(&thread->kernel_handler, 0, sizeof(thread->kernel_handler));
@@ -190,7 +196,7 @@ dword_t create_thread_internal(process_t *proc, thread_state_t *initial_state, d
     if (proc != kernel_process)
     {
         thread->previous_mode = USER_MODE;
-
+        thread->in_kernel = 0;
         thread->state.regs.cs = get_user_code_selector();
         thread->state.regs.data_selector = get_user_data_selector();
     }
@@ -327,6 +333,7 @@ found:
             bump_address_space(&current_thread->owner_process->memory_space);
         }
 
+        if (current_thread->terminating && !current_thread->in_kernel) current_thread->terminated = TRUE;
         if (current_thread->terminated) destroy_thread(current_thread);
         current_thread = next_thread;
         current_thread->quantum = QUANTUM;
@@ -496,25 +503,8 @@ found:
 
 dword_t terminate_thread_internal(thread_t *thread, dword_t exit_code)
 {
-    critical_t critical;
-    thread->terminating = TRUE;
-
-    if (thread != current_thread)
-    {
-        wait_condition_t cond = { .type = WAIT_UNTIL_EQUAL, .pointer = (dword_t*)&thread->in_kernel, .value = 0 };
-        wait_result_t result = scheduler_wait(&cond, NO_TIMEOUT);
-        if (result == WAIT_CANCELED) return ERR_CANCELED;
-    }
-
-    enter_critical(&critical);
-
     thread->exit_code = exit_code;
-    thread->terminated = TRUE;
-    if (thread != current_thread) destroy_thread(thread);
-
-    leave_critical(&critical);
-
-    if (thread == current_thread) syscall_yield_quantum();
+    thread->terminating = TRUE;
     return ERR_SUCCESS;
 }