Browse Source

Improve process/thread termination.

coderain 5 years ago
parent
commit
52c5ee0487
5 changed files with 43 additions and 67 deletions
  1. 1 0
      kernel/include/process.h
  2. 7 3
      kernel/src/exception.c
  3. 3 7
      kernel/src/interrupt.c
  4. 21 36
      kernel/src/process.c
  5. 11 21
      kernel/src/thread.c

+ 1 - 0
kernel/include/process.h

@@ -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

+ 7 - 3
kernel/src/exception.c

@@ -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

+ 3 - 7
kernel/src/interrupt.c

@@ -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));
         }
     }

+ 21 - 36
kernel/src/process.c

@@ -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)

+ 11 - 21
kernel/src/thread.c

@@ -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;
 }