From f19d112a1a40fb9fec9fe00a4e6afbbd80ac8717 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 11 Jul 2013 14:17:17 +0100 Subject: [PATCH] Small fixes following review . Copied from Perforce Change: 182993 ServerID: perforce.ravenbrook.com --- mps/code/protxc.c | 82 +++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/mps/code/protxc.c b/mps/code/protxc.c index 6dbe0d91c13..1bee3dbf741 100644 --- a/mps/code/protxc.c +++ b/mps/code/protxc.c @@ -1,22 +1,24 @@ -/* protxc.c: PROTECTION EXCPETION HANDLER FOR OS X MACH +/* protxc.c: PROTECTION EXCEPTION HANDLER FOR OS X MACH * * $Id$ * Copyright (c) 2013 Ravenbrook Limited. See end of file for license. * - * This is the protection exception handling code for Mac OS X using the + * This is the protection exception handling code for OS X using the * Mach interface (not pthreads). * * In Mach, a thread that hits protected memory is suspended, and a message * is sent to a separate handler thread. + * * The handler thread can fix things up and continue the suspended thread by * sending back a "success" reply. It can forward the message to another * handler of the same kind, or it can forward the message to another handler * at the next level out (the levels are thread, task, host) by sending a * "fail" reply. * - * In Mac OS X, pthreads are implemented by Mach threads. (The implementation - * is part of the XNU source code at opensource.apple.com. [copy to import?]) - * So we can use some pthread interfaces for convenience in setting up threads. + * In OS X, pthreads are implemented by Mach threads. (The implementation is + * part of the XNU source code at opensource.apple.com. [copy to import?]) So + * we can use some pthread interfaces (pthread_create, pthread_once) for + * convenience in setting up threads. * * This module sets up an exception handling thread for the EXC_BAD_ACCESS * exceptions that will be caused by the MPS shield (read/write barriers). @@ -58,6 +60,7 @@ #include "protxc.h" #include /* see .trans.stdlib */ +#include /* see .trans.stdlib */ #include @@ -73,8 +76,8 @@ #if !defined(MPS_OS_XC) #error "protxc.c is OS X specific" #endif -#ifndef PROTECTION -#error "protxc.c implements protection, but PROTECTION is not set" +#if !defined(PROTECTION) +#error "protxc.c implements protection, but PROTECTION is not defined" #endif SRCID(protxc, "$Id$"); @@ -124,7 +127,7 @@ typedef __Reply__exception_raise_state_identity_t protReplyStruct; /* protExcPort -- exception message receiving Mach port * * This will be the port that will receive messages for our exception - * handler, initialized by protSetup. + * handler, initialized by protSetupInner. */ static mach_port_name_t protExcPort = MACH_PORT_NULL; @@ -176,7 +179,7 @@ static void protMustSend(mach_msg_header_t *head) /* protCatchOne -- catch one EXC_BAD_ACCESS exception message. * - * Mac OS X provides a function exc_server (in + * OS X provides a function exc_server (in * /usr/lib/system/libsystem_kernel.dylib) that's documented in the XNU * sources * and generated by the Mach Interface Generator (mig). It unpacks @@ -187,7 +190,7 @@ static void protMustSend(mach_msg_header_t *head) * steal those names in case the client program is using them too. * * 2. It fails anyway in Xcode's default "Release" build with hidden - * symbols, because it uses dlsym to find those handler functins, and + * symbols, because it uses dlsym to find those handler functions, and * dlsym can't find them. * * So instead this function duplicates the work of exc_server, and is shorter @@ -203,12 +206,13 @@ static void protCatchOne(void) mach_msg_return_t mr; protReplyStruct reply; + AVER(MACH_PORT_VALID(protExcPort)); mr = mach_msg(&request.Head, - MACH_RCV_MSG, + /* option */ MACH_RCV_MSG, /* send_size */ 0, - /* receive_size */ sizeof(request), - protExcPort, - /* timeout */ 0, + /* receive_limit */ sizeof(request), + /* receive_name */ protExcPort, + /* timeout */ MACH_MSG_TIMEOUT_NONE, /* notify */ MACH_PORT_NULL); AVER(mr == MACH_MSG_SUCCESS); if (mr != MACH_MSG_SUCCESS) @@ -284,16 +288,17 @@ static void *protCatchThread(void *p) { extern void ProtThreadRegister(Bool setup) { kern_return_t kr; - mach_msg_type_number_t old_cnt; - exception_mask_t old_mask; - exception_behavior_t behaviour; - mach_port_t old_port; - exception_behavior_t old_behaviour; - thread_state_flavor_t old_flavor; + mach_msg_type_number_t old_exception_count; + exception_mask_t old_exception_masks; + exception_behavior_t behavior; + mach_port_t old_exception_ports; + exception_behavior_t old_behaviors; + thread_state_flavor_t old_flavors; mach_port_t self; static mach_port_t setupThread = MACH_PORT_NULL; self = mach_thread_self(); + AVER(MACH_PORT_VALID(self)); /* Avoid setting up the exception handler for the setup thread twice, in the case where the mutator registers that thread twice. */ @@ -310,46 +315,53 @@ extern void ProtThreadRegister(Bool setup) with thread state and identity information in the message. The MACH_EXCEPTION_CODES flag causes the code fields to be passed 64-bits wide, matching protRequestStruct. */ - behaviour = (exception_behavior_t)(EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES); + behavior = (exception_behavior_t)(EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES); + AVER(MACH_PORT_VALID(protExcPort)); kr = thread_swap_exception_ports(self, EXC_MASK_BAD_ACCESS, protExcPort, - behaviour, + behavior, THREAD_STATE_FLAVOR, - &old_mask, - &old_cnt, - &old_port, - &old_behaviour, - &old_flavor); + &old_exception_masks, + &old_exception_count, + &old_exception_ports, + &old_behaviors, + &old_flavors); AVER(kr == KERN_SUCCESS); if (kr != KERN_SUCCESS) mach_error("ERROR: MPS thread_swap_exception_ports", kr); /* .trans.must */ - AVER(old_mask == EXC_MASK_BAD_ACCESS); - AVER(old_cnt == 1); - AVER(old_port == MACH_PORT_NULL); /* .assume.only-port */ + AVER(old_exception_masks == EXC_MASK_BAD_ACCESS); + AVER(old_exception_count == 1); + AVER(old_exception_ports == MACH_PORT_NULL); /* .assume.only-port */ } /* ProtSetup -- set up protection exception handling */ -static void protSetup(void) +static void protSetupInner(void) { kern_return_t kr; int pr; pthread_t excThread; + mach_port_t self; /* Create a port to send and receive exceptions. */ - kr = mach_port_allocate(mach_task_self(), + self = mach_task_self(); + AVER(MACH_PORT_VALID(self)); + kr = mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, &protExcPort); AVER(kr == KERN_SUCCESS); if (kr != KERN_SUCCESS) mach_error("ERROR: MPS mach_port_allocate", kr); /* .trans.must */ + AVER(MACH_PORT_VALID(protExcPort)); /* Allow me to send exceptions on this port. */ /* TODO: Find out why this is necessary. */ - kr = mach_port_insert_right(mach_task_self(), - protExcPort, protExcPort , + self = mach_task_self(); + AVER(MACH_PORT_VALID(self)); + kr = mach_port_insert_right(self, + protExcPort, protExcPort, MACH_MSG_TYPE_MAKE_SEND); AVER(kr == KERN_SUCCESS); if (kr != KERN_SUCCESS) @@ -374,7 +386,7 @@ void ProtSetup(void) /* ProtSetup may be called several times if the client creates more than one arena, but we still only want one exception handling thread. */ - pr = pthread_once(&prot_setup_once, protSetup); + pr = pthread_once(&prot_setup_once, protSetupInner); AVER(pr == 0); if (pr != 0) fprintf(stderr, "ERROR: MPS pthread_once: %d\n", pr); /* .trans.must */