diff options
Diffstat (limited to 'ipc/mach_msg.c')
-rw-r--r-- | ipc/mach_msg.c | 457 |
1 files changed, 0 insertions, 457 deletions
diff --git a/ipc/mach_msg.c b/ipc/mach_msg.c index 5824d8d..31ecf89 100644 --- a/ipc/mach_msg.c +++ b/ipc/mach_msg.c @@ -1776,460 +1776,3 @@ mach_msg_interrupt(thread) 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 */ |