diff options
-rw-r--r-- | include/mach/syscall_sw.h | 2 | ||||
-rw-r--r-- | kern/ipc_mig.c | 41 | ||||
-rw-r--r-- | kern/ipc_mig.h | 5 | ||||
-rw-r--r-- | kern/syscall_sw.c | 2 | ||||
-rw-r--r-- | tests/include/syscalls.h | 1 |
5 files changed, 50 insertions, 1 deletions
diff --git a/include/mach/syscall_sw.h b/include/mach/syscall_sw.h index 89597e99..94ca6678 100644 --- a/include/mach/syscall_sw.h +++ b/include/mach/syscall_sw.h @@ -95,6 +95,8 @@ kernel_trap(syscall_mach_port_insert_right,-74,4) kernel_trap(syscall_mach_port_allocate_name,-75,3) kernel_trap(syscall_thread_depress_abort,-76,1) +kernel_trap(thread_set_self_state,-77,3) + /* These are screwing up glibc somehow. */ /*kernel_trap(syscall_device_writev_request,-39,6)*/ /*kernel_trap(syscall_device_write_request,-40,6)*/ diff --git a/kern/ipc_mig.c b/kern/ipc_mig.c index b753a25f..18ac88ef 100644 --- a/kern/ipc_mig.c +++ b/kern/ipc_mig.c @@ -55,6 +55,7 @@ #include <device/dev_hdr.h> #include <device/device_types.h> #include <device/ds_routines.h> +#include <machine/pcb.h> /* * Routine: mach_msg_send_from_kernel @@ -879,6 +880,46 @@ kern_return_t syscall_thread_depress_abort(mach_port_name_t thread) } /* + * Routine: thread_set_self_state [mach trap] + * Purpose: + * Set current thread's state, as if with + * thread_set_state() RPC. + * + * When setting the generic state (one that contains + * the register used for syscall return value) succeeds, + * the successful return does not overwire the just-set + * register value. + * Conditions: + * Nothing locked. + * Returns: + * Nothing at all Successfully set generic state. + * KERN_SUCCESS Successfully set other state. + * KERN_INVALID_ARGUMENT Invalid flavor or state. + */ +kern_return_t thread_set_self_state( + int flavor, + thread_state_t new_state, + natural_t new_state_count) +{ + thread_t t = current_thread(); + kern_return_t kr; + natural_t new_state_copy[150]; + + if (new_state_count <= 0 || new_state_count > 150) + return KERN_INVALID_ARGUMENT; + + if (copyin(new_state, new_state_copy, new_state_count * sizeof(natural_t))) + return KERN_INVALID_ARGUMENT; + + thread_set_syscall_return(t, KERN_SUCCESS); + kr = thread_setstatus(t, flavor, new_state_copy, new_state_count); + if (kr == KERN_SUCCESS) + thread_exception_return(); + + return kr; +} + +/* * Device traps -- these are way experimental. */ io_return_t diff --git a/kern/ipc_mig.h b/kern/ipc_mig.h index 422e8d84..f5d8b07a 100644 --- a/kern/ipc_mig.h +++ b/kern/ipc_mig.h @@ -124,6 +124,11 @@ extern kern_return_t syscall_mach_port_allocate_name( extern kern_return_t syscall_thread_depress_abort(mach_port_name_t thread); +extern kern_return_t thread_set_self_state( + int flavor, + thread_state_t new_state, + natural_t new_state_count); + extern io_return_t syscall_device_write_request( mach_port_name_t device_name, mach_port_name_t reply_name, diff --git a/kern/syscall_sw.c b/kern/syscall_sw.c index 4249b711..15270b1a 100644 --- a/kern/syscall_sw.c +++ b/kern/syscall_sw.c @@ -160,7 +160,7 @@ mach_trap_t mach_trap_table[] = { MACH_TRAP(syscall_mach_port_insert_right, 4), /* 74 */ MACH_TRAP(syscall_mach_port_allocate_name, 3), /* 75 */ MACH_TRAP(syscall_thread_depress_abort, 1), /* 76 */ - MACH_TRAP(kern_invalid, 0), /* 77 */ + MACH_TRAP(thread_set_self_state, 3), /* 77 */ MACH_TRAP(kern_invalid, 0), /* 78 */ MACH_TRAP(kern_invalid, 0), /* 79 */ diff --git a/tests/include/syscalls.h b/tests/include/syscalls.h index f958154c..33c37a1a 100644 --- a/tests/include/syscalls.h +++ b/tests/include/syscalls.h @@ -70,6 +70,7 @@ MACH_SYSCALL4(65, kern_return_t, syscall_vm_allocate, mach_port_t, vm_offset_t*, MACH_SYSCALL3(66, kern_return_t, syscall_vm_deallocate, mach_port_t, vm_offset_t, vm_size_t) MACH_SYSCALL3(72, kern_return_t, syscall_mach_port_allocate, mach_port_t, mach_port_right_t, mach_port_t*) MACH_SYSCALL2(73, kern_return_t, syscall_mach_port_deallocate, mach_port_t, mach_port_t) +MACH_SYSCALL3(77, kern_return_t, thread_set_self_state, int, natural_t *, natural_t) /* todo: swtch_pri swtch ... |