--- Gnu-Mach/ipc/mach_msg.c 2020/09/02 04:36:56 1.1 +++ Gnu-Mach/ipc/mach_msg.c 2020/09/02 04:45:06 1.1.1.3 @@ -36,15 +36,14 @@ * Exported message traps. See mach/message.h. */ -#include -#include - #include #include #include #include #include +#include #include +#include #include #include #include @@ -59,15 +58,11 @@ #include #include #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 /* * Routine: mach_msg_send @@ -199,7 +194,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 +207,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 +218,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 +272,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 +283,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 +309,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 +369,6 @@ mach_msg_receive_continue() thread_syscall_return(mr); /*NOTREACHED*/ } -#endif /* CONTINUATIONS */ /* * Routine: mach_msg_trap [mach trap] @@ -401,7 +392,6 @@ mach_msg_trap(msg, option, send_size, rc { mach_msg_return_t mr; -#ifdef CONTINUATIONS /* first check for common cases */ if (option == (MACH_SEND_MSG|MACH_RCV_MSG)) { @@ -470,7 +460,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; @@ -635,14 +625,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; @@ -754,13 +736,6 @@ 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 */ @@ -859,9 +834,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)); @@ -1272,7 +1244,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 +1313,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))) @@ -1380,28 +1349,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. @@ -1697,7 +1644,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 +1662,6 @@ mach_msg_trap(msg, option, send_size, rc return MACH_MSG_SUCCESS; } -#ifdef CONTINUATIONS /* * Routine: mach_msg_continue * Purpose: @@ -1728,7 +1673,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; @@ -1819,461 +1764,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