--- ../gc6.2alpha5.today/os_dep.c Tue May 20 14:32:30 2003 +++ os_dep.c Thu May 29 21:02:52 2003 @@ -3272,13 +3272,18 @@ # endif /* PCR_VDB */ #if defined(MPROTECT_VDB) && defined(DARWIN) -/* Much of this exception handling code is based on the xnu (Darwin's kernel) souce - code, Timothy J. Wood's "Mach Exception Handlers 101" post to the macosx-dev - mailing list, and Apple's GDB source. */ +/* 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. + www.omnigroup.com/mailman/archive/macosx-dev/2000-June/002030.html + 3. macosx-nat.c from Apple's GDB source code. +*/ -/* There seem to be numerous problems with darwin's mach exception handling. I'm - pretty sure they are not problems in my code. Search for BROKEN_EXCEPTION_HANDLING - for more information. */ +/* There seem to be numerous problems with darwin's mach exception handling. + I'm pretty sure they are not problems in my code. Search for + BROKEN_EXCEPTION_HANDLING for more information. */ #define BROKEN_EXCEPTION_HANDLING #include @@ -3288,7 +3293,7 @@ #include #include -/* These are not defined in any header */ +/* These are not defined in any header, although they are documented */ extern boolean_t exc_server(mach_msg_header_t *,mach_msg_header_t *); extern kern_return_t exception_raise( mach_port_t,mach_port_t,mach_port_t, @@ -3328,7 +3333,9 @@ mach_msg_header_t head; } GC_msg_t; -typedef enum { GC_MP_NORMAL, GC_MP_DISCARDING, GC_MP_STOPPED } GC_mprotect_state_t; +typedef enum { + GC_MP_NORMAL, GC_MP_DISCARDING, GC_MP_STOPPED +} GC_mprotect_state_t; /* FIXME: 1 and 2 seem to be safe to use in the msgh_id field, but it isn't documented. Use the source and see if they @@ -3366,7 +3373,8 @@ GC_ports.reply, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if(r != MACH_MSG_SUCCESS) ABORT("mach_msg failed in GC_mprotect_thread_notify"); + if(r != MACH_MSG_SUCCESS) + ABORT("mach_msg failed in GC_mprotect_thread_notify"); if(buf.msg.head.msgh_id != ID_ACK) ABORT("invalid ack in GC_mprotect_thread_notify"); } @@ -3391,7 +3399,8 @@ MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if(r != MACH_MSG_SUCCESS) ABORT("mach_msg failed in GC_mprotect_thread_reply"); + if(r != MACH_MSG_SUCCESS) + ABORT("mach_msg failed in GC_mprotect_thread_reply"); } void GC_mprotect_stop() { @@ -3406,34 +3415,26 @@ #define GC_mprotect_state GC_MP_NORMAL #endif -/* Based somewhat on xnu's bsd/uxkern/ux_exception.c */ static void *GC_mprotect_thread(void *arg) { mach_msg_return_t r; + /* 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. */ struct { - mach_msg_header_t Head; - NDR_record_t NDR; - kern_return_t RetCode; + mach_msg_header_t head; + char data[256]; } reply; struct { - mach_msg_header_t Head; - /* start of the kernel processed data */ + mach_msg_header_t head; mach_msg_body_t msgh_body; - mach_msg_port_descriptor_t thread; - mach_msg_port_descriptor_t task; - /* end of the kernel processed data */ - NDR_record_t NDR; - exception_type_t exception; - mach_msg_type_number_t codeCnt; - exception_data_t code; - /* some times RCV_TO_LARGE probs */ - char pad[512]; + char data[1024]; } msg; mach_msg_id_t id; for(;;) { r = mach_msg( - &msg.Head, + &msg.head, MACH_RCV_MSG|MACH_RCV_LARGE| (GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0), 0, @@ -3442,7 +3443,7 @@ GC_mprotect_state == GC_MP_DISCARDING ? 0 : MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - id = r == MACH_MSG_SUCCESS ? msg.Head.msgh_id : -1; + id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1; #if defined(THREADS) if(GC_mprotect_state == GC_MP_DISCARDING) { @@ -3457,12 +3458,11 @@ #endif if(r != MACH_MSG_SUCCESS) { - GC_err_printf2("mach_msg failed with %d %s\n", (int)r,mach_error_string(r)); + GC_err_printf2("mach_msg failed with %d %s\n", + (int)r,mach_error_string(r)); ABORT("mach_msg failed"); } - /*GC_printf1("I got a message with id: %d\n",id);*/ - switch(id) { #if defined(THREADS) case ID_STOP: @@ -3479,12 +3479,13 @@ #endif /* THREADS */ default: /* Handle the message (calls catch_exception_raise) */ - if(!exc_server(&msg.Head,&reply.Head)) ABORT("exc_server failed"); + if(!exc_server(&msg.head,&reply.head)) + ABORT("exc_server failed"); /* Send the reply */ r = mach_msg( - &reply.Head, + &reply.head, MACH_SEND_MSG, - reply.Head.msgh_size, + reply.head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, @@ -3493,8 +3494,9 @@ /* This will fail if the thread dies, but the thread shouldn't die... */ #ifdef BROKEN_EXCEPTION_HANDLING - GC_err_printf2("mach_msg failed with %d %s while sending exc reply\n", - (int)r,mach_error_string(r)); + GC_err_printf2( + "mach_msg failed with %d %s while sending exc reply\n", + (int)r,mach_error_string(r)); #else ABORT("mach_msg failed while sending exception reply"); #endif @@ -3505,7 +3507,7 @@ return NULL; } -/* All this SIGBUS code shouldn't be unnecessary. All protection faults should +/* All this SIGBUS code shouldn't be necessary. All protection faults should be going throught the mach exception handler. However, it seems a SIGBUS is occasionally sent for some unknown reason. Even more odd, it seems to be meaningless and safe to ignore. */ @@ -3524,7 +3526,7 @@ /* Ugh... some seem safe to ignore, but too many in a row probably means trouble. GC_sigbus_count is reset for each mach exception that is handled */ - if(GC_sigbus_count > 8) { + if(GC_sigbus_count >= 8) { ABORT("Got more than 8 SIGBUSs in a row!"); } else { GC_sigbus_count++; @@ -3541,10 +3543,12 @@ exception_mask_t mask; # ifdef PRINTSTATS - GC_printf0("Inititalizing mach/darwin mprotect virtual dirty bit implementation\n"); + GC_printf0("Inititalizing mach/darwin mprotect virtual dirty bit " + "implementation\n"); # endif # ifdef BROKEN_EXCEPTION_HANDLING - GC_err_printf0("GC: WARNING: Enabling workarounds for various darwin exception handling bugs.\n"); + GC_err_printf0("GC: WARNING: Enabling workarounds for various darwin " + "exception handling bugs.\n"); # endif GC_dirty_maintained = TRUE; if (GC_page_size % HBLKSIZE != 0) { @@ -3618,7 +3622,9 @@ #endif /* BROKEN_EXCEPTION_HANDLING */ } -/* Based on Apple's gdb sources */ +/* The source code for Apple's GDB was used as a reference for the exception + forwarding code. This code is similar to be GDB code only because there is + only one way to do it. */ static kern_return_t GC_forward_exception( mach_port_t thread, mach_port_t task, @@ -3638,28 +3644,30 @@ for(i=0;i