|
@@ -34,14 +34,13 @@ static const char *exception_names[] = {
|
|
|
"Memory Access Fault",
|
|
|
};
|
|
|
|
|
|
-static void raise_exception_internal(registers_t *regs, processor_mode_t mode, exception_info_t *info)
|
|
|
+static void raise_exception_internal(thread_t *thread, processor_mode_t mode, exception_info_t *info)
|
|
|
{
|
|
|
- thread_t *thread = get_current_thread();
|
|
|
- if (thread == NULL) KERNEL_CRASH_WITH_REGS(exception_names[info->number], regs);
|
|
|
-
|
|
|
if (mode == USER_MODE)
|
|
|
{
|
|
|
+ bool_t current = (thread == get_current_thread());
|
|
|
thread->user_exception_info = *info;
|
|
|
+ registers_t *regs = (current || (thread->in_kernel > 0)) ? thread->last_context : &thread->state.regs;
|
|
|
|
|
|
if (thread->user_handler.eip)
|
|
|
{
|
|
@@ -52,18 +51,22 @@ static void raise_exception_internal(registers_t *regs, processor_mode_t mode, e
|
|
|
ASSERT((regs->cs & 0xFFFC) == 0 || SEGMENT_RPL(regs->cs) == 3);
|
|
|
ASSERT((regs->data_selector & 0xFFFC) == 0 || SEGMENT_RPL(regs->data_selector) == 3);
|
|
|
|
|
|
- registers_ext_t *regs_ext = (registers_ext_t*)regs;
|
|
|
- regs_ext->esp3 = regs->esp;
|
|
|
+ if (current || (thread->in_kernel > 0))
|
|
|
+ {
|
|
|
+ registers_ext_t *regs_ext = (registers_ext_t*)regs;
|
|
|
+ regs_ext->esp3 = regs->esp;
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- enable_ints();
|
|
|
- syscall_terminate(INVALID_HANDLE, 1);
|
|
|
- ASSERT(FALSE);
|
|
|
+ if (current) enable_ints();
|
|
|
+ terminate_thread_internal(thread, 1);
|
|
|
+ ASSERT(!current);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
+ ASSERT(thread == get_current_thread());
|
|
|
thread->kernel_exception_info = *info;
|
|
|
|
|
|
if (thread->kernel_handler.eip)
|
|
@@ -73,7 +76,7 @@ static void raise_exception_internal(registers_t *regs, processor_mode_t mode, e
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- KERNEL_CRASH_WITH_REGS(exception_names[info->number], regs);
|
|
|
+ KERNEL_CRASH_WITH_REGS(exception_names[info->number], thread->last_context);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -152,10 +155,12 @@ static void exception_handler(registers_t *regs, byte_t int_num)
|
|
|
KERNEL_CRASH_WITH_REGS("Unexpected CPU exception", regs);
|
|
|
}
|
|
|
|
|
|
- raise_exception_internal(regs, previous_mode, &info);
|
|
|
+ thread_t *thread = get_current_thread();
|
|
|
+ if (thread == NULL) KERNEL_CRASH_WITH_REGS(exception_names[info.number], regs);
|
|
|
+ raise_exception_internal(thread, previous_mode, &info);
|
|
|
}
|
|
|
|
|
|
-sysret_t syscall_raise_exception(exception_info_t *info)
|
|
|
+sysret_t syscall_raise_exception(handle_t thread_handle, const exception_info_t *info)
|
|
|
{
|
|
|
exception_info_t safe_info;
|
|
|
|
|
@@ -172,8 +177,21 @@ sysret_t syscall_raise_exception(exception_info_t *info)
|
|
|
safe_info = *info;
|
|
|
}
|
|
|
|
|
|
- thread_t *thread = get_current_thread();
|
|
|
- raise_exception_internal(&thread->state.regs, get_previous_mode(), &safe_info);
|
|
|
+ thread_t *thread = NULL;
|
|
|
+
|
|
|
+ if (thread_handle == INVALID_HANDLE)
|
|
|
+ {
|
|
|
+ thread = get_current_thread();
|
|
|
+ reference(&thread->header);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (!reference_by_handle(thread_handle, OBJECT_THREAD, (object_t**)&thread)) return ERR_INVALID;
|
|
|
+ }
|
|
|
+
|
|
|
+ raise_exception_internal(thread, USER_MODE, &safe_info);
|
|
|
+
|
|
|
+ dereference(&thread->header);
|
|
|
return ERR_SUCCESS;
|
|
|
}
|
|
|
|
|
@@ -225,7 +243,7 @@ sysret_t syscall_save_exception_handler(exception_handler_t *old_handler)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-sysret_t syscall_restore_exception_handler(exception_handler_t *old_handler)
|
|
|
+sysret_t syscall_restore_exception_handler(const exception_handler_t *old_handler)
|
|
|
{
|
|
|
thread_t *thread = get_current_thread();
|
|
|
|