aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mach/syscall_sw.h2
-rw-r--r--kern/ipc_mig.c41
-rw-r--r--kern/ipc_mig.h5
-rw-r--r--kern/syscall_sw.c2
-rw-r--r--tests/include/syscalls.h1
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 ...