2 * This is the Darwin incarnation of OS-dependent routines. See also
7 * This software is part of the SBCL system. See the README file for
10 * This software is derived from the CMU CL system, which was
11 * written at Carnegie Mellon University and released into the
12 * public domain. The software is in the public domain and is
13 * provided with absolutely no warranty. See the COPYING and CREDITS
14 * files for more information.
23 #include <mach-o/dyld.h>
27 #ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER
28 #include <mach/mach.h>
32 os_get_runtime_executable_path(int external)
34 char path[PATH_MAX + 1];
35 uint32_t size = sizeof(path);
37 if (_NSGetExecutablePath(path, &size) == -1)
40 return copied_string(path);
43 #ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER
45 /* exc_server handles mach exception messages from the kernel and
46 * calls catch exception raise. We use the system-provided
47 * mach_msg_server, which, I assume, calls exc_server in a loop.
50 extern boolean_t exc_server();
53 mach_exception_handler(void *port)
55 mach_msg_server(exc_server, 2048, (mach_port_t) port, 0);
56 /* mach_msg_server should never return, but it should dispatch mach
57 * exceptions to our catch_exception_raise function
59 lose("mach_msg_server returned");
62 /* Sets up the thread that will listen for mach exceptions. note that
63 the exception handlers will be run on this thread. This is
64 different from the BSD-style signal handling situation in which the
65 signal handlers run in the relevant thread directly. */
67 mach_port_t mach_exception_handler_port_set = MACH_PORT_NULL;
68 mach_port_t current_mach_task = MACH_PORT_NULL;
71 setup_mach_exception_handling_thread()
74 pthread_t mach_exception_handling_thread = NULL;
77 current_mach_task = mach_task_self();
79 /* allocate a mach_port for this process */
80 ret = mach_port_allocate(current_mach_task,
81 MACH_PORT_RIGHT_PORT_SET,
82 &mach_exception_handler_port_set);
84 /* create the thread that will receive the mach exceptions */
86 FSHOW((stderr, "Creating mach_exception_handler thread!\n"));
88 pthread_attr_init(&attr);
89 pthread_create(&mach_exception_handling_thread,
91 mach_exception_handler,
92 (void*) mach_exception_handler_port_set);
93 pthread_attr_destroy(&attr);
95 return mach_exception_handling_thread;
98 /* tell the kernel that we want EXC_BAD_ACCESS exceptions sent to the
99 exception port (which is being listened to do by the mach
100 exception handling thread). */
102 mach_thread_init(mach_port_t thread_exception_port)
105 mach_port_t current_mach_thread;
107 /* allocate a named port for the thread */
108 FSHOW((stderr, "Allocating mach port %x\n", thread_exception_port));
109 ret = mach_port_allocate_name(current_mach_task,
110 MACH_PORT_RIGHT_RECEIVE,
111 thread_exception_port);
113 lose("mach_port_allocate_name failed with return_code %d\n", ret);
116 /* establish the right for the thread_exception_port to send messages */
117 ret = mach_port_insert_right(current_mach_task,
118 thread_exception_port,
119 thread_exception_port,
120 MACH_MSG_TYPE_MAKE_SEND);
122 lose("mach_port_insert_right failed with return_code %d\n", ret);
125 current_mach_thread = mach_thread_self();
126 ret = thread_set_exception_ports(current_mach_thread,
127 EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION,
128 thread_exception_port,
132 lose("thread_set_exception_ports failed with return_code %d\n", ret);
135 ret = mach_port_deallocate (current_mach_task, current_mach_thread);
137 lose("mach_port_deallocate failed with return_code %d\n", ret);
140 ret = mach_port_move_member(current_mach_task,
141 thread_exception_port,
142 mach_exception_handler_port_set);
144 lose("mach_port_move_member failed with return_code %d\n", ret);
151 setup_mach_exceptions() {
152 setup_mach_exception_handling_thread();
153 mach_thread_init(THREAD_STRUCT_TO_EXCEPTION_PORT(all_threads));
160 setup_mach_exceptions();
167 void darwin_init(void)
169 setup_mach_exception_handling_thread();