]> gitweb.factorcode.org Git - factor.git/commitdiff
VM: Refactor mach_signal to Factor style
authorErik Charlebois <erikcharlebois@gmail.com>
Sun, 12 May 2013 02:11:09 +0000 (22:11 -0400)
committerErik Charlebois <erikcharlebois@gmail.com>
Sun, 12 May 2013 17:24:45 +0000 (13:24 -0400)
vm/mach_signal.cpp
vm/mach_signal.hpp

index a4fe269b3d495c202634d099f781dfd13df2381c..abbf7ae8c669a0ae4ae3024544f1f696366fb1f0 100644 (file)
@@ -12,243 +12,220 @@ Modified for Factor by Slava Pestov */
 
 #include "master.hpp"
 
-namespace factor
-{
+namespace factor {
 
 /* The exception port on which our thread listens. */
 mach_port_t our_exception_port;
 
 /* The following sources were used as a *reference* for this exception handling
-code:
-1. Apple's mach/xnu documentation
-2. Timothy J. Wood's "Mach Exception Handlers 101" post to the
-omnigroup's macosx-dev list.
-http://www.wodeveloper.com/omniLists/macosx-dev/2000/June/msg00137.html */
+   code:
+
+   1. Apple's mach/xnu documentation
+   2. Timothy J. Wood's "Mach Exception Handlers 101" post to the
+      omnigroup's macosx-dev list.
+      http://www.wodeveloper.com/omniLists/macosx-dev/2000/June/msg00137.html */
 
 /* Modify a suspended thread's thread_state so that when the thread resumes
-executing, the call frame of the current C primitive (if any) is rewound, and
-the appropriate Factor error is thrown from the top-most Factor frame. */
-void factor_vm::call_fault_handler(
-       exception_type_t exception,
-       exception_data_type_t code,
-       MACH_EXC_STATE_TYPE *exc_state,
-       MACH_THREAD_STATE_TYPE *thread_state,
-       MACH_FLOAT_STATE_TYPE *float_state)
-{
-       cell handler = 0;
-
-       if(exception == EXC_BAD_ACCESS)
-       {
-               signal_fault_addr = MACH_EXC_STATE_FAULT(exc_state);
-               signal_fault_pc = (cell)MACH_PROGRAM_COUNTER(thread_state);
-               verify_memory_protection_error(signal_fault_addr);
-               handler = (cell)factor::memory_signal_handler_impl;
-       }
-       else if(exception == EXC_ARITHMETIC && code != MACH_EXC_INTEGER_DIV)
-       {
-               signal_fpu_status = fpu_status(mach_fpu_status(float_state));
-               mach_clear_fpu_status(float_state);
-               handler = (cell)factor::fp_signal_handler_impl;
-       }
-       else
-       {
-               switch(exception)
-               {
-               case EXC_ARITHMETIC: signal_number = SIGFPE; break;
-               case EXC_BAD_INSTRUCTION: signal_number = SIGILL; break;
-               default: signal_number = SIGABRT; break;
-               }
-
-               handler = (cell)factor::synchronous_signal_handler_impl;
-       }
-
-       FACTOR_ASSERT(handler != 0);
-
-       dispatch_signal_handler(
-               (cell*)&MACH_STACK_POINTER(thread_state),
-               (cell*)&MACH_PROGRAM_COUNTER(thread_state),
-               (cell)handler
-       );
+   executing, the call frame of the current C primitive (if any) is rewound, and
+   the appropriate Factor error is thrown from the top-most Factor frame. */
+void factor_vm::call_fault_handler(exception_type_t exception,
+                                   exception_data_type_t code,
+                                   MACH_EXC_STATE_TYPE* exc_state,
+                                   MACH_THREAD_STATE_TYPE* thread_state,
+                                   MACH_FLOAT_STATE_TYPE* float_state) {
+  cell handler = 0;
+
+  if (exception == EXC_BAD_ACCESS) {
+    signal_fault_addr = MACH_EXC_STATE_FAULT(exc_state);
+    signal_fault_pc = (cell) MACH_PROGRAM_COUNTER(thread_state);
+    verify_memory_protection_error(signal_fault_addr);
+    handler = (cell) factor::memory_signal_handler_impl;
+  } else if (exception == EXC_ARITHMETIC && code != MACH_EXC_INTEGER_DIV) {
+    signal_fpu_status = fpu_status(mach_fpu_status(float_state));
+    mach_clear_fpu_status(float_state);
+    handler = (cell) factor::fp_signal_handler_impl;
+  } else {
+    switch (exception) {
+      case EXC_ARITHMETIC:
+        signal_number = SIGFPE;
+        break;
+      case EXC_BAD_INSTRUCTION:
+        signal_number = SIGILL;
+        break;
+      default:
+        signal_number = SIGABRT;
+        break;
+    }
+
+    handler = (cell) factor::synchronous_signal_handler_impl;
+  }
+
+  FACTOR_ASSERT(handler != 0);
+
+  dispatch_signal_handler((cell*)&MACH_STACK_POINTER(thread_state),
+                          (cell*)&MACH_PROGRAM_COUNTER(thread_state),
+                          (cell) handler);
 }
 
-static void call_fault_handler(
-       mach_port_t thread,
-       exception_type_t exception,
-       exception_data_type_t code,
-       MACH_EXC_STATE_TYPE *exc_state,
-       MACH_THREAD_STATE_TYPE *thread_state,
-       MACH_FLOAT_STATE_TYPE *float_state)
-{
-       /* Look up the VM instance involved */
-       THREADHANDLE thread_id = pthread_from_mach_thread_np(thread);
-       FACTOR_ASSERT(thread_id);
-       std::map<THREADHANDLE, factor_vm*>::const_iterator vm = thread_vms.find(thread_id);
-
-       /* Handle the exception */
-       if (vm != thread_vms.end())
-               vm->second->call_fault_handler(exception,code,exc_state,thread_state,float_state);
+static void call_fault_handler(mach_port_t thread, exception_type_t exception,
+                               exception_data_type_t code,
+                               MACH_EXC_STATE_TYPE* exc_state,
+                               MACH_THREAD_STATE_TYPE* thread_state,
+                               MACH_FLOAT_STATE_TYPE* float_state) {
+  /* Look up the VM instance involved */
+  THREADHANDLE thread_id = pthread_from_mach_thread_np(thread);
+  FACTOR_ASSERT(thread_id);
+  std::map<THREADHANDLE, factor_vm*>::const_iterator vm =
+      thread_vms.find(thread_id);
+
+  /* Handle the exception */
+  if (vm != thread_vms.end())
+    vm->second->call_fault_handler(exception, code, exc_state, thread_state,
+                                   float_state);
 }
 
 /* Handle an exception by invoking the user's fault handler and/or forwarding
-the duty to the previously installed handlers. */
-extern "C"
-kern_return_t
-catch_exception_raise (mach_port_t exception_port,
-       mach_port_t thread,
-       mach_port_t task,
-       exception_type_t exception,
-       exception_data_t code,
-       mach_msg_type_number_t code_count)
-{
-       /* 10.6 likes to report exceptions from child processes too. Ignore those */
-       if(task != mach_task_self()) return KERN_FAILURE;
-
-       /* Get fault information and the faulting thread's register contents..
-       
-       See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_get_state.html.  */
-       MACH_EXC_STATE_TYPE exc_state;
-       mach_msg_type_number_t exc_state_count = MACH_EXC_STATE_COUNT;
-       if (thread_get_state (thread, MACH_EXC_STATE_FLAVOR,
-                             (natural_t *)&exc_state, &exc_state_count)
-               != KERN_SUCCESS)
-       {
-               /* The thread is supposed to be suspended while the exception
-               handler is called. This shouldn't fail. */
-               return KERN_FAILURE;
-       }
-
-       MACH_THREAD_STATE_TYPE thread_state;
-       mach_msg_type_number_t thread_state_count = MACH_THREAD_STATE_COUNT;
-       if (thread_get_state (thread, MACH_THREAD_STATE_FLAVOR,
-                             (natural_t *)&thread_state, &thread_state_count)
-               != KERN_SUCCESS)
-       {
-               /* The thread is supposed to be suspended while the exception
-               handler is called. This shouldn't fail. */
-               return KERN_FAILURE;
-       }
-
-       MACH_FLOAT_STATE_TYPE float_state;
-       mach_msg_type_number_t float_state_count = MACH_FLOAT_STATE_COUNT;
-       if (thread_get_state (thread, MACH_FLOAT_STATE_FLAVOR,
-                             (natural_t *)&float_state, &float_state_count)
-               != KERN_SUCCESS)
-       {
-               /* The thread is supposed to be suspended while the exception
-               handler is called. This shouldn't fail. */
-               return KERN_FAILURE;
-       }
-
-       /* Modify registers so to have the thread resume executing the
-       fault handler */
-       call_fault_handler(thread,exception,code[0],&exc_state,&thread_state,&float_state);
-
-       /* Set the faulting thread's register contents..
-       
-       See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_set_state.html.  */
-       if (thread_set_state (thread, MACH_FLOAT_STATE_FLAVOR,
-                             (natural_t *)&float_state, float_state_count)
-               != KERN_SUCCESS)
-       {
-               return KERN_FAILURE;
-       }
-
-       if (thread_set_state (thread, MACH_THREAD_STATE_FLAVOR,
-                             (natural_t *)&thread_state, thread_state_count)
-               != KERN_SUCCESS)
-       {
-               return KERN_FAILURE;
-       }
-
-       return KERN_SUCCESS;
+   the duty to the previously installed handlers.      */
+extern "C" kern_return_t catch_exception_raise(
+    mach_port_t exception_port, mach_port_t thread, mach_port_t task,
+    exception_type_t exception, exception_data_t code,
+    mach_msg_type_number_t code_count) {
+  /* 10.6 likes to report exceptions from child processes too. Ignore those */
+  if (task != mach_task_self())
+    return KERN_FAILURE;
+
+  /* Get fault information and the faulting thread's register contents..
+     See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_get_state.html. */
+  MACH_EXC_STATE_TYPE exc_state;
+  mach_msg_type_number_t exc_state_count = MACH_EXC_STATE_COUNT;
+  if (thread_get_state(thread, MACH_EXC_STATE_FLAVOR, (natural_t*)&exc_state,
+                       &exc_state_count) !=
+      KERN_SUCCESS) {
+    /* The thread is supposed to be suspended while the exception
+       handler is called. This shouldn't fail. */
+    return KERN_FAILURE;
+  }
+
+  MACH_THREAD_STATE_TYPE thread_state;
+  mach_msg_type_number_t thread_state_count = MACH_THREAD_STATE_COUNT;
+  if (thread_get_state(thread, MACH_THREAD_STATE_FLAVOR,
+                       (natural_t*)&thread_state, &thread_state_count) !=
+      KERN_SUCCESS) {
+    /* The thread is supposed to be suspended while the exception
+       handler is called. This shouldn't fail. */
+    return KERN_FAILURE;
+  }
+
+  MACH_FLOAT_STATE_TYPE float_state;
+  mach_msg_type_number_t float_state_count = MACH_FLOAT_STATE_COUNT;
+  if (thread_get_state(thread, MACH_FLOAT_STATE_FLAVOR,
+                       (natural_t*)&float_state, &float_state_count) !=
+      KERN_SUCCESS) {
+    /* The thread is supposed to be suspended while the exception
+       handler is called. This shouldn't fail. */
+    return KERN_FAILURE;
+  }
+
+  /* Modify registers so to have the thread resume executing the
+     fault handler */
+  call_fault_handler(thread, exception, code[0], &exc_state, &thread_state,
+                     &float_state);
+
+  /* Set the faulting thread's register contents..
+     See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_set_state.html. */
+  if (thread_set_state(thread, MACH_FLOAT_STATE_FLAVOR,
+                       (natural_t*)&float_state, float_state_count) !=
+      KERN_SUCCESS) {
+    return KERN_FAILURE;
+  }
+
+  if (thread_set_state(thread, MACH_THREAD_STATE_FLAVOR,
+                       (natural_t*)&thread_state, thread_state_count) !=
+      KERN_SUCCESS) {
+    return KERN_FAILURE;
+  }
+
+  return KERN_SUCCESS;
 }
 
 /* The main function of the thread listening for exceptions.  */
-static void *
-mach_exception_thread (void *arg)
-{
-       for (;;)
-       {
-               /* These two structures contain some private kernel data. We don't need
-               to access any of it so we don't bother defining a proper struct. The
-               correct definitions are in the xnu source code. */
-               /* Buffer for a message to be received.  */
-               struct
-               {
-                       mach_msg_header_t head;
-                       mach_msg_body_t msgh_body;
-                       char data[1024];
-               }
-               msg;
-               /* Buffer for a reply message.  */
-               struct
-               {
-                       mach_msg_header_t head;
-                       char data[1024];
-               }
-               reply;
-
-               mach_msg_return_t retval;
-
-               /* Wait for a message on the exception port.  */
-               retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0,
-                       sizeof (msg), our_exception_port,
-                       MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-               if (retval != MACH_MSG_SUCCESS)
-               {
-                       abort ();
-               }
-
-               /* Handle the message: Call exc_server, which will call
-               catch_exception_raise and produce a reply message.  */
-               exc_server (&msg.head, &reply.head);
-
-               /* Send the reply.  */
-               if (mach_msg (&reply.head, MACH_SEND_MSG, reply.head.msgh_size,
-                       0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)
-                       != MACH_MSG_SUCCESS)
-               {
-                       abort ();
-               }
-       }
-       return NULL; // quiet warning
+static void* mach_exception_thread(void* arg) {
+  for (;;) {
+    /* These two structures contain some private kernel data. We don't need
+       to access any of it so we don't bother defining a proper struct. The
+       correct definitions are in the xnu source code. */
+    /* Buffer for a message to be received. */
+    struct {
+      mach_msg_header_t head;
+      mach_msg_body_t msgh_body;
+      char data[1024];
+    } msg;
+    /* Buffer for a reply message. */
+    struct {
+      mach_msg_header_t head;
+      char data[1024];
+    } reply;
+
+    mach_msg_return_t retval;
+
+    /* Wait for a message on the exception port. */
+    retval =
+        mach_msg(&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(msg),
+                 our_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+    if (retval != MACH_MSG_SUCCESS) {
+      abort();
+    }
+
+    /* Handle the message: Call exc_server, which will call
+       catch_exception_raise and produce a reply message. */
+    exc_server(&msg.head, &reply.head);
+
+    /* Send the reply. */
+    if (mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0,
+                 MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL) !=
+        MACH_MSG_SUCCESS) {
+      abort();
+    }
+  }
+  return NULL;  // quiet warning
 }
 
 /* Initialize the Mach exception handler thread. */
-void mach_initialize ()
-{
-       mach_port_t self;
-       exception_mask_t mask;
-
-       self = mach_task_self ();
-
-       /* Allocate a port on which the thread shall listen for exceptions.  */
-       if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port)
-               != KERN_SUCCESS)
-               fatal_error("mach_port_allocate() failed",0);
-
-       /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html.  */
-       if (mach_port_insert_right (self, our_exception_port, our_exception_port,
-               MACH_MSG_TYPE_MAKE_SEND)
-               != KERN_SUCCESS)
-               fatal_error("mach_port_insert_right() failed",0);
-
-       /* The exceptions we want to catch. */
-       mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC;
-
-       /* Create the thread listening on the exception port.  */
-       start_thread(mach_exception_thread,NULL);
-
-       /* Replace the exception port info for these exceptions with our own.
-       Note that we replace the exception port for the entire task, not only
-       for a particular thread.  This has the effect that when our exception
-       port gets the message, the thread specific exception port has already
-       been asked, and we don't need to bother about it.
-       See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html.  */
-       if (task_set_exception_ports (self, mask, our_exception_port,
-               EXCEPTION_DEFAULT, MACHINE_THREAD_STATE)
-               != KERN_SUCCESS)
-               fatal_error("task_set_exception_ports() failed",0);
+void mach_initialize() {
+  mach_port_t self;
+  exception_mask_t mask;
+
+  self = mach_task_self();
+
+  /* Allocate a port on which the thread shall listen for exceptions. */
+  if (mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port) !=
+      KERN_SUCCESS)
+    fatal_error("mach_port_allocate() failed", 0);
+
+  /* See
+   * http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html.
+   */
+  if (mach_port_insert_right(self, our_exception_port, our_exception_port,
+                             MACH_MSG_TYPE_MAKE_SEND) !=
+      KERN_SUCCESS)
+    fatal_error("mach_port_insert_right() failed", 0);
+
+  /* The exceptions we want to catch. */
+  mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC;
+
+  /* Create the thread listening on the exception port. */
+  start_thread(mach_exception_thread, NULL);
+
+  /* Replace the exception port info for these exceptions with our own.
+     Note that we replace the exception port for the entire task, not only
+     for a particular thread. This has the effect that when our exception
+     port gets the message, the thread specific exception port has already
+     been asked, and we don't need to bother about it. See
+     http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html.        */
+  if (task_set_exception_ports(self, mask, our_exception_port,
+                               EXCEPTION_DEFAULT, MACHINE_THREAD_STATE) !=
+      KERN_SUCCESS)
+    fatal_error("task_set_exception_ports() failed", 0);
 }
 
 }
index a1961359d1a58b0036b47655d0e70f96190790a3..acf9f69788175793d3d217bd325f9b250637d42d 100644 (file)
@@ -36,48 +36,28 @@ Modified for Factor by Slava Pestov */
    allowing the thread to continue from the point of the exception; otherwise,
    no reply message is sent and the called routine must have dealt with the
    exception thread directly.  */
-extern "C" boolean_t exc_server (mach_msg_header_t *request_msg, mach_msg_header_t *reply_msg);
+extern "C" boolean_t exc_server(mach_msg_header_t* request_msg,
+                                mach_msg_header_t* reply_msg);
 
 /* http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/catch_exception_raise.html
    These functions are defined in this file, and called by exc_server.
    FIXME: What needs to be done when this code is put into a shared library? */
-extern "C"
-kern_return_t
-catch_exception_raise (mach_port_t exception_port,
-                      mach_port_t thread,
-                      mach_port_t task,
-                      exception_type_t exception,
-                      exception_data_t code,
-                      mach_msg_type_number_t code_count);
-extern "C"
-kern_return_t
-catch_exception_raise_state (mach_port_t exception_port,
-                            exception_type_t exception,
-                            exception_data_t code,
-                            mach_msg_type_number_t code_count,
-                            thread_state_flavor_t *flavor,
-                            thread_state_t in_state,
-                            mach_msg_type_number_t in_state_count,
-                            thread_state_t out_state,
-                            mach_msg_type_number_t *out_state_count);
-
-extern "C"
-kern_return_t
-catch_exception_raise_state_identity (mach_port_t exception_port,
-                                     mach_port_t thread,
-                                     mach_port_t task,
-                                     exception_type_t exception,
-                                     exception_data_t code,
-                                     mach_msg_type_number_t codeCnt,
-                                     thread_state_flavor_t *flavor,
-                                     thread_state_t in_state,
-                                     mach_msg_type_number_t in_state_count,
-                                     thread_state_t out_state,
-                                     mach_msg_type_number_t *out_state_count);
-
-namespace factor
-{
-
-void mach_initialize ();
-
-}
+extern "C" kern_return_t catch_exception_raise(
+    mach_port_t exception_port, mach_port_t thread, mach_port_t task,
+    exception_type_t exception, exception_data_t code,
+    mach_msg_type_number_t code_count);
+extern "C" kern_return_t catch_exception_raise_state(
+    mach_port_t exception_port, exception_type_t exception,
+    exception_data_t code, mach_msg_type_number_t code_count,
+    thread_state_flavor_t* flavor, thread_state_t in_state,
+    mach_msg_type_number_t in_state_count, thread_state_t out_state,
+    mach_msg_type_number_t* out_state_count);
+
+extern "C" kern_return_t catch_exception_raise_state_identity(
+    mach_port_t exception_port, mach_port_t thread, mach_port_t task,
+    exception_type_t exception, exception_data_t code,
+    mach_msg_type_number_t codeCnt, thread_state_flavor_t* flavor,
+    thread_state_t in_state, mach_msg_type_number_t in_state_count,
+    thread_state_t out_state, mach_msg_type_number_t* out_state_count);
+
+namespace factor { void mach_initialize(); }