--- Gnu-Mach/ipc/mach_msg.c 2020/09/02 04:36:56 1.1.1.1 +++ Gnu-Mach/ipc/mach_msg.c 2020/09/02 04:47:18 1.1.1.4 @@ -36,17 +36,17 @@ * Exported message traps. See mach/message.h. */ -#include -#include - #include #include #include #include #include +#include #include +#include #include #include +#include #include #include #include @@ -59,15 +59,8 @@ #include #include #include - - - -extern void exception_raise_continue(); -extern void exception_raise_continue_fast(); -#ifndef CONTINUATIONS -#define mach_msg_receive_continue 0 -#define msg_receive_continue 0 -#endif +#include +#include /* * Routine: mach_msg_send @@ -95,12 +88,12 @@ extern void exception_raise_continue_fas */ mach_msg_return_t -mach_msg_send(msg, option, send_size, time_out, notify) - mach_msg_header_t *msg; - mach_msg_option_t option; - mach_msg_size_t send_size; - mach_msg_timeout_t time_out; - mach_port_t notify; +mach_msg_send( + mach_msg_header_t *msg, + mach_msg_option_t option, + mach_msg_size_t send_size, + mach_msg_timeout_t time_out, + mach_port_t notify) { ipc_space_t space = current_space(); vm_map_t map = current_map(); @@ -177,13 +170,13 @@ mach_msg_send(msg, option, send_size, ti */ mach_msg_return_t -mach_msg_receive(msg, option, rcv_size, rcv_name, time_out, notify) - mach_msg_header_t *msg; - mach_msg_option_t option; - mach_msg_size_t rcv_size; - mach_port_t rcv_name; - mach_msg_timeout_t time_out; - mach_port_t notify; +mach_msg_receive( + mach_msg_header_t *msg, + mach_msg_option_t option, + mach_msg_size_t rcv_size, + mach_port_t rcv_name, + mach_msg_timeout_t time_out, + mach_port_t notify) { ipc_thread_t self = current_thread(); ipc_space_t space = current_space(); @@ -199,7 +192,6 @@ mach_msg_receive(msg, option, rcv_size, return mr; /* hold ref for object; mqueue is locked */ -#ifdef CONTINUATIONS /* * ipc_mqueue_receive may not return, because if we block * then our kernel stack may be discarded. So we save @@ -213,7 +205,6 @@ mach_msg_receive(msg, option, rcv_size, self->ith_notify = notify; self->ith_object = object; self->ith_mqueue = mqueue; -#endif if (option & MACH_RCV_LARGE) { mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT, @@ -225,12 +216,12 @@ mach_msg_receive(msg, option, rcv_size, if (mr != MACH_MSG_SUCCESS) { if (mr == MACH_RCV_TOO_LARGE) { mach_msg_size_t real_size = - (mach_msg_size_t) (natural_t) kmsg; + (mach_msg_size_t) (vm_offset_t) kmsg; assert(real_size > rcv_size); - (void) copyout((vm_offset_t) &real_size, - (vm_offset_t) &msg->msgh_size, + (void) copyout(&real_size, + &msg->msgh_size, sizeof(mach_msg_size_t)); } @@ -279,7 +270,6 @@ mach_msg_receive(msg, option, rcv_size, return ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size); } -#ifdef CONTINUATIONS /* * Routine: mach_msg_receive_continue * Purpose: @@ -291,7 +281,7 @@ mach_msg_receive(msg, option, rcv_size, */ void -mach_msg_receive_continue() +mach_msg_receive_continue(void) { ipc_thread_t self = current_thread(); ipc_space_t space = current_space(); @@ -317,12 +307,12 @@ mach_msg_receive_continue() if (mr != MACH_MSG_SUCCESS) { if (mr == MACH_RCV_TOO_LARGE) { mach_msg_size_t real_size = - (mach_msg_size_t) (natural_t) kmsg; + (mach_msg_size_t) (vm_offset_t) kmsg; assert(real_size > rcv_size); - (void) copyout((vm_offset_t) &real_size, - (vm_offset_t) &msg->msgh_size, + (void) copyout(&real_size, + &msg->msgh_size, sizeof(mach_msg_size_t)); } @@ -377,7 +367,6 @@ mach_msg_receive_continue() thread_syscall_return(mr); /*NOTREACHED*/ } -#endif /* CONTINUATIONS */ /* * Routine: mach_msg_trap [mach trap] @@ -390,27 +379,26 @@ mach_msg_receive_continue() */ mach_msg_return_t -mach_msg_trap(msg, option, send_size, rcv_size, rcv_name, time_out, notify) - mach_msg_header_t *msg; - mach_msg_option_t option; - mach_msg_size_t send_size; - mach_msg_size_t rcv_size; - mach_port_t rcv_name; - mach_msg_timeout_t time_out; - mach_port_t notify; +mach_msg_trap( + mach_msg_header_t *msg, + mach_msg_option_t option, + mach_msg_size_t send_size, + mach_msg_size_t rcv_size, + mach_port_t rcv_name, + mach_msg_timeout_t time_out, + mach_port_t notify) { mach_msg_return_t mr; -#ifdef CONTINUATIONS /* first check for common cases */ if (option == (MACH_SEND_MSG|MACH_RCV_MSG)) { - register ipc_thread_t self = current_thread(); + ipc_thread_t self = current_thread(); ipc_space_t space = self->task->itk_space; - register ipc_kmsg_t kmsg; - register ipc_port_t dest_port; + ipc_kmsg_t kmsg; + ipc_port_t dest_port; ipc_object_t rcv_object; - register ipc_mqueue_t rcv_mqueue; + ipc_mqueue_t rcv_mqueue; mach_msg_size_t reply_size; /* @@ -470,7 +458,7 @@ mach_msg_trap(msg, option, send_size, rc ikm_cache() = IKM_NULL; ikm_check_initialized(kmsg, IKM_SAVED_KMSG_SIZE); - if (copyinmsg((vm_offset_t) msg, (vm_offset_t) &kmsg->ikm_header, + if (copyinmsg(msg, &kmsg->ikm_header, send_size)) { ikm_free(kmsg); goto slow_get; @@ -494,18 +482,18 @@ mach_msg_trap(msg, option, send_size, rc switch (kmsg->ikm_header.msgh_bits) { case MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE): { - register ipc_entry_t table; - register ipc_entry_num_t size; - register ipc_port_t reply_port; + ipc_entry_t table; + ipc_entry_num_t size; + ipc_port_t reply_port; /* sending a request message */ { - register mach_port_index_t index; - register mach_port_gen_t gen; + mach_port_index_t index; + mach_port_gen_t gen; { - register mach_port_t reply_name = + mach_port_t reply_name = kmsg->ikm_header.msgh_local_port; if (reply_name != rcv_name) @@ -527,8 +515,8 @@ mach_msg_trap(msg, option, send_size, rc goto abort_request_copyin; { - register ipc_entry_t entry; - register ipc_entry_bits_t bits; + ipc_entry_t entry; + ipc_entry_bits_t bits; entry = &table[index]; bits = entry->ie_bits; @@ -548,11 +536,11 @@ mach_msg_trap(msg, option, send_size, rc /* optimized ipc_entry_lookup of dest_name */ { - register mach_port_index_t index; - register mach_port_gen_t gen; + mach_port_index_t index; + mach_port_gen_t gen; { - register mach_port_t dest_name = + mach_port_t dest_name = kmsg->ikm_header.msgh_remote_port; index = MACH_PORT_INDEX(dest_name); @@ -563,8 +551,8 @@ mach_msg_trap(msg, option, send_size, rc goto abort_request_copyin; { - register ipc_entry_t entry; - register ipc_entry_bits_t bits; + ipc_entry_t entry; + ipc_entry_bits_t bits; entry = &table[index]; bits = entry->ie_bits; @@ -635,14 +623,6 @@ mach_msg_trap(msg, option, send_size, rc goto kernel_send; } -#if NORMA_IPC - if (IP_NORMA_IS_PROXY(dest_port)) { - ip_unlock(dest_port); - ip_unlock(reply_port); - goto norma_send; - } -#endif NORMA_IPC - if (dest_port->ip_msgcount >= dest_port->ip_qlimit) goto abort_request_send_receive; @@ -669,13 +649,13 @@ mach_msg_trap(msg, option, send_size, rc } case MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0): { - register ipc_entry_num_t size; - register ipc_entry_t table; + ipc_entry_num_t size; + ipc_entry_t table; /* sending a reply message */ { - register mach_port_t reply_name = + mach_port_t reply_name = kmsg->ikm_header.msgh_local_port; if (reply_name != MACH_PORT_NULL) @@ -691,12 +671,12 @@ mach_msg_trap(msg, option, send_size, rc table = space->is_table; { - register ipc_entry_t entry; - register mach_port_gen_t gen; - register mach_port_index_t index; + ipc_entry_t entry; + mach_port_gen_t gen; + mach_port_index_t index; { - register mach_port_t dest_name = + mach_port_t dest_name = kmsg->ikm_header.msgh_remote_port; index = MACH_PORT_INDEX(dest_name); @@ -754,23 +734,16 @@ mach_msg_trap(msg, option, send_size, rc /* make sure we can queue to the destination */ assert(dest_port->ip_receiver != ipc_space_kernel); -#if NORMA_IPC - if (IP_NORMA_IS_PROXY(dest_port)) { - is_write_unlock(space); - ip_unlock(dest_port); - goto norma_send; - } -#endif NORMA_IPC /* optimized ipc_entry_lookup/ipc_mqueue_copyin */ { - register ipc_entry_t entry; - register ipc_entry_bits_t bits; + ipc_entry_t entry; + ipc_entry_bits_t bits; { - register mach_port_index_t index; - register mach_port_gen_t gen; + mach_port_index_t index; + mach_port_gen_t gen; index = MACH_PORT_INDEX(rcv_name); gen = MACH_PORT_GEN(rcv_name); @@ -790,7 +763,7 @@ mach_msg_trap(msg, option, send_size, rc /* check type bits; looking for receive or set */ if (bits & MACH_PORT_TYPE_PORT_SET) { - register ipc_pset_t rcv_pset; + ipc_pset_t rcv_pset; rcv_pset = (ipc_pset_t) entry->ie_object; assert(rcv_pset != IPS_NULL); @@ -801,7 +774,7 @@ mach_msg_trap(msg, option, send_size, rc rcv_object = (ipc_object_t) rcv_pset; rcv_mqueue = &rcv_pset->ips_messages; } else if (bits & MACH_PORT_TYPE_RECEIVE) { - register ipc_port_t rcv_port; + ipc_port_t rcv_port; rcv_port = (ipc_port_t) entry->ie_object; assert(rcv_port != IP_NULL); @@ -859,9 +832,6 @@ mach_msg_trap(msg, option, send_size, rc assert(ip_active(dest_port)); assert(dest_port->ip_receiver != ipc_space_kernel); -#if NORMA_IPC - assert(! IP_NORMA_IS_PROXY(dest_port)); -#endif NORMA_IPC assert((dest_port->ip_msgcount < dest_port->ip_qlimit) || (MACH_MSGH_BITS_REMOTE(kmsg->ikm_header.msgh_bits) == MACH_MSG_TYPE_PORT_SEND_ONCE)); @@ -869,11 +839,11 @@ mach_msg_trap(msg, option, send_size, rc MACH_MSGH_BITS_CIRCULAR) == 0); { - register ipc_mqueue_t dest_mqueue; - register ipc_thread_t receiver; + ipc_mqueue_t dest_mqueue; + ipc_thread_t receiver; { - register ipc_pset_t dest_pset; + ipc_pset_t dest_pset; dest_pset = dest_port->ip_pset; if (dest_pset == IPS_NULL) @@ -1102,9 +1072,9 @@ mach_msg_trap(msg, option, send_size, rc ip_unlock(reply_port); { - register ipc_entry_t table; - register ipc_entry_t entry; - register mach_port_index_t index; + ipc_entry_t table; + ipc_entry_t entry; + mach_port_index_t index; /* optimized ipc_entry_get */ @@ -1119,7 +1089,7 @@ mach_msg_trap(msg, option, send_size, rc entry->ie_request = 0; { - register mach_port_gen_t gen; + mach_port_gen_t gen; assert((entry->ie_bits &~ IE_BITS_GEN_MASK) == 0); gen = entry->ie_bits + IE_BITS_GEN_ONE; @@ -1162,11 +1132,19 @@ mach_msg_trap(msg, option, send_size, rc } else ip_unlock(dest_port); - kmsg->ikm_header.msgh_bits = - MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, - MACH_MSG_TYPE_PORT_SEND); + if (! ipc_port_flag_protected_payload(dest_port)) { + kmsg->ikm_header.msgh_bits = MACH_MSGH_BITS( + MACH_MSG_TYPE_PORT_SEND_ONCE, + MACH_MSG_TYPE_PORT_SEND); + kmsg->ikm_header.msgh_local_port = dest_name; + } else { + kmsg->ikm_header.msgh_bits = MACH_MSGH_BITS( + MACH_MSG_TYPE_PORT_SEND_ONCE, + MACH_MSG_TYPE_PROTECTED_PAYLOAD); + kmsg->ikm_header.msgh_protected_payload = + dest_port->ip_protected_payload; + } kmsg->ikm_header.msgh_remote_port = reply_name; - kmsg->ikm_header.msgh_local_port = dest_name; goto fast_put; abort_request_copyout: @@ -1176,7 +1154,7 @@ mach_msg_trap(msg, option, send_size, rc } case MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0): { - register mach_port_t dest_name; + mach_port_t dest_name; /* receiving a reply message */ @@ -1200,17 +1178,25 @@ mach_msg_trap(msg, option, send_size, rc dest_name = MACH_PORT_NULL; } - kmsg->ikm_header.msgh_bits = - MACH_MSGH_BITS(0, - MACH_MSG_TYPE_PORT_SEND_ONCE); + if (! ipc_port_flag_protected_payload(dest_port)) { + kmsg->ikm_header.msgh_bits = MACH_MSGH_BITS( + 0, + MACH_MSG_TYPE_PORT_SEND_ONCE); + kmsg->ikm_header.msgh_local_port = dest_name; + } else { + kmsg->ikm_header.msgh_bits = MACH_MSGH_BITS( + 0, + MACH_MSG_TYPE_PROTECTED_PAYLOAD); + kmsg->ikm_header.msgh_protected_payload = + dest_port->ip_protected_payload; + } kmsg->ikm_header.msgh_remote_port = MACH_PORT_NULL; - kmsg->ikm_header.msgh_local_port = dest_name; goto fast_put; } case MACH_MSGH_BITS_COMPLEX| MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0): { - register mach_port_t dest_name; + mach_port_t dest_name; /* receiving a complex reply message */ @@ -1234,12 +1220,23 @@ mach_msg_trap(msg, option, send_size, rc dest_name = MACH_PORT_NULL; } - kmsg->ikm_header.msgh_bits = - MACH_MSGH_BITS_COMPLEX | - MACH_MSGH_BITS(0, - MACH_MSG_TYPE_PORT_SEND_ONCE); + if (! ipc_port_flag_protected_payload(dest_port)) { + kmsg->ikm_header.msgh_bits = + MACH_MSGH_BITS_COMPLEX + | MACH_MSGH_BITS( + 0, + MACH_MSG_TYPE_PORT_SEND_ONCE); + kmsg->ikm_header.msgh_local_port = dest_name; + } else { + kmsg->ikm_header.msgh_bits = + MACH_MSGH_BITS_COMPLEX + | MACH_MSGH_BITS( + 0, + MACH_MSG_TYPE_PROTECTED_PAYLOAD); + kmsg->ikm_header.msgh_protected_payload = + dest_port->ip_protected_payload; + } kmsg->ikm_header.msgh_remote_port = MACH_PORT_NULL; - kmsg->ikm_header.msgh_local_port = dest_name; mr = ipc_kmsg_copyout_body( (vm_offset_t) (&kmsg->ikm_header + 1), @@ -1272,7 +1269,7 @@ mach_msg_trap(msg, option, send_size, rc ikm_check_initialized(kmsg, kmsg->ikm_size); if ((kmsg->ikm_size != IKM_SAVED_KMSG_SIZE) || - copyoutmsg((vm_offset_t) &kmsg->ikm_header, (vm_offset_t) msg, + copyoutmsg(&kmsg->ikm_header, msg, reply_size) || (ikm_cache() != IKM_NULL)) goto slow_put; @@ -1341,9 +1338,6 @@ mach_msg_trap(msg, option, send_size, rc } if (ip_active(dest_port) && -#if NORMA_IPC - (! IP_NORMA_IS_PROXY(dest_port)) && -#endif NORMA_IPC ((dest_port->ip_msgcount < dest_port->ip_qlimit) || (MACH_MSGH_BITS_REMOTE(kmsg->ikm_header.msgh_bits) == MACH_MSG_TYPE_PORT_SEND_ONCE))) @@ -1353,7 +1347,7 @@ mach_msg_trap(msg, option, send_size, rc * It will work if this is a request message. */ - register ipc_port_t reply_port; + ipc_port_t reply_port; reply_port = (ipc_port_t) kmsg->ikm_header.msgh_local_port; @@ -1380,28 +1374,6 @@ mach_msg_trap(msg, option, send_size, rc ip_unlock(dest_port); goto slow_send; -#if NORMA_IPC - norma_send: - /* - * Nothing is locked. We have acquired kmsg, but - * we still need to send it and receive a reply. - */ - - mr = norma_ipc_send(kmsg); - if (mr != MACH_MSG_SUCCESS) { - mr |= ipc_kmsg_copyout_pseudo(kmsg, space, - current_map()); - - assert(kmsg->ikm_marequest == IMAR_NULL); - (void) ipc_kmsg_put(msg, kmsg, - kmsg->ikm_header.msgh_size); - thread_syscall_return(mr); - /*NOTREACHED*/ - } - - goto slow_get_rcv_port; -#endif NORMA_IPC - kernel_send: /* * Special case: send message to kernel services. @@ -1410,7 +1382,7 @@ mach_msg_trap(msg, option, send_size, rc */ { - register ipc_port_t reply_port; + ipc_port_t reply_port; /* * Perform the kernel function. @@ -1697,7 +1669,6 @@ mach_msg_trap(msg, option, send_size, rc thread_syscall_return(MACH_MSG_SUCCESS); /*NOTREACHED*/ } -#endif /* CONTINUATIONS */ if (option & MACH_SEND_MSG) { mr = mach_msg_send(msg, option, send_size, @@ -1716,7 +1687,6 @@ mach_msg_trap(msg, option, send_size, rc return MACH_MSG_SUCCESS; } -#ifdef CONTINUATIONS /* * Routine: mach_msg_continue * Purpose: @@ -1728,7 +1698,7 @@ mach_msg_trap(msg, option, send_size, rc */ void -mach_msg_continue() +mach_msg_continue(void) { ipc_thread_t thread = current_thread(); task_t task = thread->task; @@ -1790,8 +1760,7 @@ mach_msg_continue() */ boolean_t -mach_msg_interrupt(thread) - thread_t thread; +mach_msg_interrupt(thread_t thread) { ipc_mqueue_t mqueue; @@ -1819,461 +1788,3 @@ mach_msg_interrupt(thread) thread->swap_func = thread_exception_return; return TRUE; } -#endif /* CONTINUATIONS */ - -#if MACH_IPC_COMPAT - -/* - * Routine: msg_return_translate - * Purpose: - * Translate from new error code to old error code. - */ - -msg_return_t -msg_return_translate(mr) - mach_msg_return_t mr; -{ - switch (mr &~ MACH_MSG_MASK) { - case MACH_MSG_SUCCESS: - return 0; /* SEND_SUCCESS/RCV_SUCCESS/RPC_SUCCESS */ - - case MACH_SEND_NO_BUFFER: - case MACH_SEND_NO_NOTIFY: - printf("msg_return_translate: %x -> interrupted\n", mr); - return SEND_INTERRUPTED; - - case MACH_SEND_MSG_TOO_SMALL: - return SEND_MSG_TOO_SMALL; - case MACH_SEND_INVALID_DATA: - case MACH_SEND_INVALID_MEMORY: - return SEND_INVALID_MEMORY; - case MACH_SEND_TIMED_OUT: - return SEND_TIMED_OUT; - case MACH_SEND_INTERRUPTED: - return SEND_INTERRUPTED; - case MACH_SEND_INVALID_DEST: - case MACH_SEND_INVALID_REPLY: - case MACH_SEND_INVALID_RIGHT: - case MACH_SEND_INVALID_TYPE: - return SEND_INVALID_PORT; - case MACH_SEND_WILL_NOTIFY: - return SEND_WILL_NOTIFY; - case MACH_SEND_NOTIFY_IN_PROGRESS: - return SEND_NOTIFY_IN_PROGRESS; - - case MACH_RCV_INVALID_NAME: - case MACH_RCV_IN_SET: - case MACH_RCV_PORT_DIED: - return RCV_INVALID_PORT; - case MACH_RCV_TOO_LARGE: - return RCV_TOO_LARGE; - case MACH_RCV_TIMED_OUT: - return RCV_TIMED_OUT; - case MACH_RCV_INTERRUPTED: - return RCV_INTERRUPTED; - case MACH_RCV_PORT_CHANGED: - return RCV_PORT_CHANGE; - case MACH_RCV_INVALID_DATA: - return RCV_INVALID_MEMORY; - - case MACH_SEND_IN_PROGRESS: - case MACH_SEND_INVALID_NOTIFY: - case MACH_SEND_INVALID_HEADER: - case MACH_RCV_IN_PROGRESS: - case MACH_RCV_INVALID_NOTIFY: - case MACH_RCV_HEADER_ERROR: - case MACH_RCV_BODY_ERROR: - default: -#if MACH_ASSERT - assert(!"msg_return_translate"); -#else - panic("msg_return_translate"); -#endif - } -} - -/* - * Routine: msg_send_trap [mach trap] - * Purpose: - * Send a message. - * Conditions: - * Nothing locked. - * Returns: - */ - -msg_return_t -msg_send_trap(msg, option, send_size, time_out) - msg_header_t *msg; - msg_option_t option; - msg_size_t send_size; - msg_timeout_t time_out; -{ - ipc_space_t space = current_space(); - vm_map_t map = current_map(); - ipc_kmsg_t kmsg; - mach_msg_return_t mr; - - send_size = (send_size + 3) & ~3; /* round up */ - - if (send_size > MSG_SIZE_MAX) - return SEND_MSG_TOO_LARGE; - - mr = ipc_kmsg_get((mach_msg_header_t *) msg, - (mach_msg_size_t) send_size, - &kmsg); - if (mr != MACH_MSG_SUCCESS) - return msg_return_translate(mr); - - mr = ipc_kmsg_copyin_compat(kmsg, space, map); - if (mr != MACH_MSG_SUCCESS) { - ikm_free(kmsg); - return msg_return_translate(mr); - } - - if (option & SEND_NOTIFY) { - mr = ipc_mqueue_send(kmsg, MACH_SEND_TIMEOUT, - ((option & SEND_TIMEOUT) ? - (mach_msg_timeout_t) time_out : - MACH_MSG_TIMEOUT_NONE)); - if (mr == MACH_SEND_TIMED_OUT) { - ipc_port_t dest = (ipc_port_t) - kmsg->ikm_header.msgh_remote_port; - - mr = ipc_marequest_create(space, dest, MACH_PORT_NULL, - &kmsg->ikm_marequest); - if (mr == MACH_MSG_SUCCESS) { - ipc_mqueue_send_always(kmsg); - return SEND_WILL_NOTIFY; - } - } - } else - mr = ipc_mqueue_send(kmsg, - ((option & SEND_TIMEOUT) ? - MACH_SEND_TIMEOUT : - MACH_MSG_OPTION_NONE), - (mach_msg_timeout_t) time_out); - - if (mr != MACH_MSG_SUCCESS) - ipc_kmsg_destroy(kmsg); - - return msg_return_translate(mr); -} - -/* - * Routine: msg_receive_trap [mach trap] - * Purpose: - * Receive a message. - * Conditions: - * Nothing locked. - * Returns: - */ - -msg_return_t -msg_receive_trap(msg, option, rcv_size, rcv_name, time_out) - msg_header_t *msg; - msg_option_t option; - msg_size_t rcv_size; - port_name_t rcv_name; - msg_timeout_t time_out; -{ - ipc_thread_t self; - ipc_space_t space = current_space(); - vm_map_t map = current_map(); - ipc_object_t object; - ipc_mqueue_t mqueue; - ipc_kmsg_t kmsg; - mach_port_seqno_t seqno; - mach_msg_return_t mr; - - mr = ipc_mqueue_copyin(space, (mach_port_t) rcv_name, - &mqueue, &object); - if (mr != MACH_MSG_SUCCESS) - return msg_return_translate(mr); - /* hold ref for object; mqueue is locked */ - -#ifdef CONTINUATIONS - /* - * ipc_mqueue_receive may not return, because if we block - * then our kernel stack may be discarded. So we save - * state here for msg_receive_continue to pick up. - */ - - self = current_thread(); - self->ith_msg = (mach_msg_header_t *) msg; - self->ith_option = (mach_msg_option_t) option; - self->ith_rcv_size = (mach_msg_size_t) rcv_size; - self->ith_timeout = (mach_msg_timeout_t) time_out; - self->ith_object = object; - self->ith_mqueue = mqueue; -#endif /* CONTINUATIONS */ - - mr = ipc_mqueue_receive(mqueue, - (option & RCV_TIMEOUT) ? - MACH_RCV_TIMEOUT : MACH_MSG_OPTION_NONE, - (mach_msg_size_t) rcv_size, - (mach_msg_timeout_t) time_out, - FALSE, msg_receive_continue, - &kmsg, &seqno); - /* mqueue is unlocked */ - ipc_object_release(object); - if (mr != MACH_MSG_SUCCESS) { - if (mr == MACH_RCV_TOO_LARGE) { - msg_size_t real_size = - (msg_size_t) (mach_msg_size_t) kmsg; - - assert(real_size > rcv_size); - - (void) copyout((vm_offset_t) &real_size, - (vm_offset_t) &msg->msg_size, - sizeof(msg_size_t)); - } - - return msg_return_translate(mr); - } - - assert(kmsg->ikm_header.msgh_size <= (mach_msg_size_t) rcv_size); - - mr = ipc_kmsg_copyout_compat(kmsg, space, map); - assert(mr == MACH_MSG_SUCCESS); - - mr = ipc_kmsg_put((mach_msg_header_t *) msg, kmsg, - kmsg->ikm_header.msgh_size); - return msg_return_translate(mr); -} - -/* - * Routine: msg_rpc_trap [mach trap] - * Purpose: - * Send and receive a message. - * Conditions: - * Nothing locked. - * Returns: - */ - -msg_return_t -msg_rpc_trap(msg, option, send_size, rcv_size, send_timeout, rcv_timeout) - msg_header_t *msg; - msg_option_t option; - msg_size_t send_size; - msg_size_t rcv_size; - msg_timeout_t send_timeout; - msg_timeout_t rcv_timeout; -{ - ipc_thread_t self; - ipc_space_t space = current_space(); - vm_map_t map = current_map(); - ipc_port_t reply; - ipc_pset_t pset; - ipc_mqueue_t mqueue; - ipc_kmsg_t kmsg; - mach_port_seqno_t seqno; - mach_msg_return_t mr; - - /* - * Instead of using msg_send_trap and msg_receive_trap, - * we implement msg_rpc_trap directly. The difference - * is how the reply port is handled. Instead of using - * ipc_mqueue_copyin, we save a reference for the reply - * port carried in the sent message. For example, - * consider a rename kernel call which changes the name - * of the call's own reply port. This is the behaviour - * of the Mach 2.5 msg_rpc_trap. - */ - - send_size = (send_size + 3) & ~3; /* round up */ - - if (send_size > MSG_SIZE_MAX) - return SEND_MSG_TOO_LARGE; - - mr = ipc_kmsg_get((mach_msg_header_t *) msg, - (mach_msg_size_t) send_size, - &kmsg); - if (mr != MACH_MSG_SUCCESS) - return msg_return_translate(mr); - - mr = ipc_kmsg_copyin_compat(kmsg, space, map); - if (mr != MACH_MSG_SUCCESS) { - ikm_free(kmsg); - return msg_return_translate(mr); - } - - reply = (ipc_port_t) kmsg->ikm_header.msgh_local_port; - if (IP_VALID(reply)) - ipc_port_reference(reply); - - if (option & SEND_NOTIFY) { - mr = ipc_mqueue_send(kmsg, MACH_SEND_TIMEOUT, - ((option & SEND_TIMEOUT) ? - (mach_msg_timeout_t) send_timeout : - MACH_MSG_TIMEOUT_NONE)); - if (mr == MACH_SEND_TIMED_OUT) { - ipc_port_t dest = (ipc_port_t) - kmsg->ikm_header.msgh_remote_port; - - mr = ipc_marequest_create(space, dest, MACH_PORT_NULL, - &kmsg->ikm_marequest); - if (mr == MACH_MSG_SUCCESS) { - ipc_mqueue_send_always(kmsg); - if (IP_VALID(reply)) - ipc_port_release(reply); - return SEND_WILL_NOTIFY; - } - } - } else - mr = ipc_mqueue_send(kmsg, - ((option & SEND_TIMEOUT) ? - MACH_SEND_TIMEOUT : - MACH_MSG_OPTION_NONE), - (mach_msg_timeout_t) send_timeout); - - if (mr != MACH_MSG_SUCCESS) { - ipc_kmsg_destroy(kmsg); - if (IP_VALID(reply)) - ipc_port_release(reply); - return msg_return_translate(mr); - } - - if (!IP_VALID(reply)) - return RCV_INVALID_PORT; - - ip_lock(reply); - if (reply->ip_receiver != space) { - ip_release(reply); - ip_check_unlock(reply); - return RCV_INVALID_PORT; - } - - assert(ip_active(reply)); - pset = reply->ip_pset; - - if (pset != IPS_NULL) { - ips_lock(pset); - if (ips_active(pset)) { - ips_unlock(pset); - ip_release(reply); - ip_unlock(reply); - return RCV_INVALID_PORT; - } - - ipc_pset_remove(pset, reply); - ips_check_unlock(pset); - assert(reply->ip_pset == IPS_NULL); - } - - mqueue = &reply->ip_messages; - imq_lock(mqueue); - ip_unlock(reply); - -#ifdef CONTINUATIONS - /* - * ipc_mqueue_receive may not return, because if we block - * then our kernel stack may be discarded. So we save - * state here for msg_receive_continue to pick up. - */ - - self = current_thread(); - self->ith_msg = (mach_msg_header_t *) msg; - self->ith_option = (mach_msg_option_t) option; - self->ith_rcv_size = (mach_msg_size_t) rcv_size; - self->ith_timeout = (mach_msg_timeout_t) rcv_timeout; - self->ith_object = (ipc_object_t) reply; - self->ith_mqueue = mqueue; -#endif /* CONTINUATIONS */ - - mr = ipc_mqueue_receive(mqueue, - (option & RCV_TIMEOUT) ? - MACH_RCV_TIMEOUT : MACH_MSG_OPTION_NONE, - (mach_msg_size_t) rcv_size, - (mach_msg_timeout_t) rcv_timeout, - FALSE, msg_receive_continue, - &kmsg, &seqno); - /* mqueue is unlocked */ - ipc_port_release(reply); - if (mr != MACH_MSG_SUCCESS) { - if (mr == MACH_RCV_TOO_LARGE) { - msg_size_t real_size = - (msg_size_t) (mach_msg_size_t) kmsg; - - assert(real_size > rcv_size); - - (void) copyout((vm_offset_t) &real_size, - (vm_offset_t) &msg->msg_size, - sizeof(msg_size_t)); - } - - return msg_return_translate(mr); - } - - assert(kmsg->ikm_header.msgh_size <= (mach_msg_size_t) rcv_size); - - mr = ipc_kmsg_copyout_compat(kmsg, space, map); - assert(mr == MACH_MSG_SUCCESS); - - mr = ipc_kmsg_put((mach_msg_header_t *) msg, - kmsg, kmsg->ikm_header.msgh_size); - return msg_return_translate(mr); -} - -#ifdef CONTINUATIONS -/* - * Routine: msg_receive_continue - * Purpose: - * Continue after blocking for a message. - * Conditions: - * Nothing locked. We are running on a new kernel stack, - * with the receive state saved in the thread. From here - * control goes back to user space. - */ - -void -msg_receive_continue() -{ - ipc_thread_t self = current_thread(); - msg_header_t *msg = (msg_header_t *) self->ith_msg; - msg_option_t option = (msg_option_t) self->ith_option; - msg_size_t rcv_size = (msg_size_t) self->ith_rcv_size; - msg_timeout_t time_out = (msg_timeout_t) self->ith_timeout; - ipc_object_t object = self->ith_object; - ipc_mqueue_t mqueue = self->ith_mqueue; - ipc_kmsg_t kmsg; - mach_port_seqno_t seqno; - mach_msg_return_t mr; - - mr = ipc_mqueue_receive(mqueue, - (option & RCV_TIMEOUT) ? - MACH_RCV_TIMEOUT : MACH_MSG_OPTION_NONE, - (mach_msg_size_t) rcv_size, - (mach_msg_timeout_t) time_out, - TRUE, msg_receive_continue, - &kmsg, &seqno); - /* mqueue is unlocked */ - ipc_object_release(object); - if (mr != MACH_MSG_SUCCESS) { - if (mr == MACH_RCV_TOO_LARGE) { - msg_size_t real_size = - (msg_size_t) (mach_msg_size_t) kmsg; - - assert(real_size > rcv_size); - - (void) copyout((vm_offset_t) &real_size, - (vm_offset_t) &msg->msg_size, - sizeof(msg_size_t)); - } - - thread_syscall_return(msg_return_translate(mr)); - /*NOTREACHED*/ - } - - assert(kmsg->ikm_header.msgh_size <= (mach_msg_size_t) rcv_size); - - mr = ipc_kmsg_copyout_compat(kmsg, current_space(), current_map()); - assert(mr == MACH_MSG_SUCCESS); - - mr = ipc_kmsg_put((mach_msg_header_t *) msg, kmsg, - kmsg->ikm_header.msgh_size); - thread_syscall_return(msg_return_translate(mr)); - /*NOTREACHED*/ -} -#endif /* CONTINUATIONS */ - -#endif MACH_IPC_COMPAT