Back to index

glibc  2.9
Functions
msgserver.c File Reference
#include <mach.h>
#include <mach/mig_errors.h>
#include <stdlib.h>
#include <assert.h>

Go to the source code of this file.

Functions

mach_msg_return_t __mach_msg_server_timeout (boolean_t(*demux)(mach_msg_header_t *request, mach_msg_header_t *reply), mach_msg_size_t max_size, mach_port_t rcv_name, mach_msg_option_t option, mach_msg_timeout_t timeout)
 weak_alias (__mach_msg_server_timeout, mach_msg_server_timeout)

Function Documentation

mach_msg_return_t __mach_msg_server_timeout ( boolean_t(*)(mach_msg_header_t *request, mach_msg_header_t *reply)  demux,
mach_msg_size_t  max_size,
mach_port_t  rcv_name,
mach_msg_option_t  option,
mach_msg_timeout_t  timeout 
)

Definition at line 75 of file msgserver.c.

{
  register mig_reply_header_t *request, *reply;
  register mach_msg_return_t mr;

  if (max_size == 0)
    {
#ifdef MACH_RCV_LARGE
      option |= MACH_RCV_LARGE;
      max_size = 2 * __vm_page_size; /* Generic.  Good? XXX */
#else
      max_size = 4 * __vm_page_size; /* XXX */
#endif
    }

  request = __alloca (max_size);
  reply = __alloca (max_size);

  while (1)
    {
    get_request:
      mr = __mach_msg (&request->Head, MACH_RCV_MSG|option,
                     0, max_size, rcv_name,
                     timeout, MACH_PORT_NULL);
      while (mr == MACH_MSG_SUCCESS)
       {
         /* We have a request message.
            Pass it to DEMUX for processing.  */

         (void) (*demux) (&request->Head, &reply->Head);
         assert (reply->Head.msgh_size <= max_size);

         switch (reply->RetCode)
           {
           case KERN_SUCCESS:
             /* Hunky dory.  */
             break;

           case MIG_NO_REPLY:
             /* The server function wanted no reply sent.
               Loop for another request.  */
             goto get_request;

           default:
             /* Some error; destroy the request message to release any
               port rights or VM it holds.  Don't destroy the reply port
               right, so we can send an error message.  */
             request->Head.msgh_remote_port = MACH_PORT_NULL;
             __mach_msg_destroy (&request->Head);
             break;
           }

         if (reply->Head.msgh_remote_port == MACH_PORT_NULL)
           {
             /* No reply port, so destroy the reply.  */
             if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
              __mach_msg_destroy (&reply->Head);
             goto get_request;
           }

         /* Send the reply and the get next request.  */

         {
           /* Swap the request and reply buffers.  mach_msg will read the
              reply message from the buffer we pass and write the new
              request message to the same buffer.  */
           void *tmp = request;
           request = reply;
           reply = tmp;
         }

         mr = __mach_msg (&request->Head,
                        MACH_SEND_MSG|MACH_RCV_MSG|option,
                        request->Head.msgh_size, max_size, rcv_name,
                        timeout, MACH_PORT_NULL);
       }

      /* A message error occurred.  */

      switch (mr)
       {
       case MACH_RCV_TOO_LARGE:
#ifdef MACH_RCV_LARGE
         /* The request message is larger than MAX_SIZE, and has not
            been dequeued.  The message header has the actual size of
            the message.  We recurse here in hopes that the compiler
            will optimize the tail-call and allocate some more stack
            space instead of way too much.  */
         return __mach_msg_server_timeout (demux, request->Head.msgh_size,
                                       rcv_name, option, timeout);
#else
         /* XXX the kernel has destroyed the msg */
         break;
#endif

       case MACH_SEND_INVALID_DEST:
         /* The reply can't be delivered, so destroy it.  This error
            indicates only that the requester went away, so we
            continue and get the next request.  */
         __mach_msg_destroy (&request->Head);
         break;

       default:
         /* Some other form of lossage; return to caller.  */
         return mr;
       }
    }
}

Here is the call graph for this function:

Definition at line 188 of file msgserver.c.

{
  return __mach_msg_server_timeout (demux, max_size, rcv_name,
                                MACH_MSG_OPTION_NONE,
                                MACH_MSG_TIMEOUT_NONE);
}

Here is the call graph for this function: