\begin{slide}{}
\begin{center}
\large\bf
\vskip 2in
Everything You Always Wanted \\
To Know About MIG$^{*}$
\vskip 1in
{}$^{*}$But Were Afraid To Ask
\end{center}
\vskip 1in
\begin{center}
Richard P. Draves \\[0.5in]
{\tt rpd@cs.cmu.edu} \\
School of Computer Science \\
Carnegie Mellon University \\
Pittsburgh, PA 15213
\end{center}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Mig}
\begin{itemize}
\item Stub generator for Mach IPC.
\item Pack, unpack, demultiplex messages.
\item NOT transparent language-level RPCs.
\item Doesn't hide IPC features.
\item Assumes client/server model.
\end{itemize}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Mig History}
\vfill
\centerline{\psfig{figure=history.ps}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Mig Programming Model}
\begin{itemize}
\item Clients call stubs
{\tiny\begin{code}
mach_port_t server_port;

kr = getbalance(server_port, &balance);
\end{code}}
\item Server loop processes requests
{\tiny\begin{code}
extern boolean_t bank_server();
mach_port_t server_port;
#define MAX_SIZE 512

(void) mach_msg_server(bank_server, MAX_SIZE,
                       server_port);

kern_return_t getbalance(server_port, balance)
    mach_port_t server_port;
    int *balance;	/* out */
{
    ...
}
\end{code}}
\end{itemize}
\end{slide}

\begin{slide}{}
\pagetitle{Mig Example}
{\tiny\begin{code}
/* file example.defs */

subsystem example 36270;

#include <mach/std_types.defs>

/* manipulate a bank account */

routine getbalance(
                server  : mach_port_t;
        out     balance : int);
\end{code}}
Client call:
{\tiny\begin{code}
#include "example.h"

    mach_port_t server;
    int balance;
    kern_return_t kr;

    kr = getbalance(server, &balance);
\end{code}}
Server function:
{\tiny\begin{code}
kern_return_t getbalance(server, balance)
    mach_port_t server;
    int *balance;               /* out */
{
    *balance = server_balance;
    return KERN_SUCCESS;
}
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Type Definitions}
{\tiny\begin{code}
/* from mach/std_types.defs */

type mach_port_t = MACH_MSG_TYPE_COPY_SEND;

type int = MACH_MSG_TYPE_INTEGER_32;

type kern_return_t = int;

/* pointer to out-of-line memory */

type pointer_t = ^array[] of MACH_MSG_TYPE_BYTE;

/* a 36-byte structure */

type mach_port_status_t = struct[9] of int;

/* C declarations for these types */

import <mach/std_types.h>;
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Asynchronous Messages}
{\tiny\begin{code}
/* file example.defs */

subsystem example 36270;

#include <mach/std_types.defs>

/* set bank account balance */

routine setbalance(
                server  : mach_port_t;
        in      balance : int);

/* set it with an asynchronous message */

simpleroutine asetbalance(
                server  : mach_port_t;
        in      balance : int);
\end{code}}
\vfill
{\small\begin{itemize}
\item Client and server code looks like RPC.
\item Message-ordering problems in multi-threaded servers.
\item Control-flow worries.
\item Not recommended for general use.
\end{itemize}}
\end{slide}

\begin{slide}{}
\pagetitle{Asynchronous Messages}
Client call:
{\tiny\begin{code}
#include "example.h"

    mach_port_t server;
    int balance;
    kern_return_t kr;

    kr = setbalance(server, balance);
    ...
    kr = asetbalance(server, balance);
\end{code}}
Server function:
{\tiny\begin{code}
kern_return_t setbalance(server, balance)
    mach_port_t server;
    int balance;                /* in */
{
    server_balance = balance;
    return KERN_SUCCESS;
}

kern_return_t asetbalance(server, balance)
    mach_port_t server;
    int balance;                /* in */
{
    server_balance = balance;
    return KERN_SUCCESS;
}
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Structure Arguments}
{\tiny\begin{code}
/* file example.defs */

subsystem example 36270;

#include <mach/std_types.defs>
#include "example_types.defs"

routine structdemo(
                server  : mach_port_t;
        in      arg1    : small_struct_t;
        out     arg2    : small_struct_t;
        inout   arg3    : small_struct_t);

/* file example_types.defs */

#include <mach/std_types.defs>
type small_struct_t = struct[3] of int;
import "example_types.h";

/* file example_types.h */

#ifndef _EXAMPLE_TYPES_H_
#define _EXAMPLE_TYPES_H_

typedef struct small_struct {
        int one;
        int two[2];
} small_struct_t;

#endif  _EXAMPLE_TYPES_H_
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Structure Arguments}
Client call:
{\tiny\begin{code}
#include "example.h"

    mach_port_t server;
    small_struct_t arg1, arg2, arg3;
    kern_return_t kr;

    kr = structdemo(server, arg1, &arg2, &arg3);
\end{code}}
Server function:
{\tiny\begin{code}
kern_return_t structdemo(server, arg1, arg2, arg3)
    mach_port_t server;
    small_struct_t arg1;        /* in */
    small_struct_t *arg2;       /* out */
    small_struct_t *arg3;       /* inout */
{
    *arg2 = *arg3;
    *arg3 = arg1;
    return KERN_SUCCESS;
}
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Out-Of-Line Arguments}
{\tiny\begin{code}
/* file example.defs */

subsystem example 36270;

#include <mach/std_types.defs>
#include "example_types.defs"

routine oolmemorydemo(
                server  : mach_port_t;
        in      arg1    : some_memory_t;
        out     arg2    : some_memory_t);

/* file example_types.defs */

/*
 * Variable-sized out-of-line memory:
 * Mig type name is some_memory_t,
 * C type name is vm_address_t
 */

type some_memory_t = ^array[] of MACH_MSG_TYPE_BYTE
        ctype: vm_address_t;

/* for C declaration of vm_address_t */

import <mach/machine/vm_types.h>;
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Out-Of-Line Arguments}
Client call:
{\tiny\begin{code}
#include "example.h"

    mach_port_t server;
    vm_address_t arg1, arg2;
    vm_size_t size1, size2;
    kern_return_t kr;

    (void) vm_allocate(mach_task_self(), &arg1, size1, TRUE);

    kr = oolmemorydemo(server, arg1, size1, &arg2, &size2);

    (void) vm_deallocate(mach_task_self(), arg1, size1);
    (void) vm_deallocate(mach_task_self(), arg2, size2);
\end{code}}
Server function:
{\tiny\begin{code}
kern_return_t oolmemorydemo(server, arg1, size1, arg2, size2)
    mach_port_t server;
    vm_address_t arg1;          /* in */
    vm_size_t size1;            /* in */
    vm_address_t *arg2;         /* out */
    vm_size_t *size2;           /* out */
{
    *arg2 = arg1;
    *size2 = size1;
    return KERN_SUCCESS;
}
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Deallocation}
{\tiny\begin{code}
/* file example.defs */

subsystem example 36270;

#include <mach/std_types.defs>
#include "example_types.defs"

/* deallocate arg2 while sending the reply */

routine oolmemorydemo(
                server  : mach_port_t;
        in      arg1    : some_memory_t;
        out     arg2    : some_memory_t, dealloc);
\end{code}}
Server function:
{\tiny\begin{code}
kern_return_t oolmemorydemo(server, arg1, size1, arg2, size2)
    mach_port_t server;
    vm_address_t arg1;          /* in */
    vm_size_t size1;            /* in */
    vm_address_t *arg2;         /* out, dealloc */
    vm_size_t *size2;           /* out */
{
    /*
     *  Out-of-line memory from the client in arg1 is
     *  returned to the client with automatic deallocation.
     */

    *arg2 = arg1;
    *size2 = size1;
    return KERN_SUCCESS;
}
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Dynamic Deallocation}
{\tiny\begin{code}
/* file example.defs */

subsystem example 36270;

#include <mach/std_types.defs>
#include "example_types.defs"

/* generate extra dealloc argument for arg1,
   always deallocate arg2 while sending the reply */

routine oolmemorydemo(
                server  : mach_port_t;
        in      arg1    : some_memory_t, dealloc[];
        out     arg2    : some_memory_t, dealloc);
\end{code}}
Client call:
{\tiny\begin{code}
#include "example.h"

    mach_port_t server;
    vm_address_t arg1, arg2;
    vm_size_t size1, size2;
    kern_return_t kr;

    (void) vm_allocate(mach_task_self(), &arg1, size1, TRUE);

    /* deallocate arg1 while sending the request */
    kr = oolmemorydemo(server, arg1, size1, TRUE,
                       &arg2, &size2);

    (void) vm_deallocate(mach_task_self(), arg2, size2);
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Port Arguments}
{\small\begin{itemize}
\item Normal port rights:
\begin{itemize}
\item {\tt MACH_MSG_TYPE_COPY_SEND},
      {\tt MACH_MSG_TYPE_MAKE_SEND},
      {\tt MACH_MSG_TYPE_MOVE_SEND}
\item {\tt MACH_MSG_TYPE_MAKE_SEND_ONCE},
      {\tt MACH_MSG_TYPE_MOVE_SEND_ONCE}
\item {\tt MACH_MSG_TYPE_MOVE_RECEIVE}
\end{itemize}
\item ``Polymorphic'' port rights:
\begin{itemize}
\item {\tt MACH_MSG_TYPE_PORT_SEND}
\item {\tt MACH_MSG_TYPE_PORT_SEND_ONCE}
\item {\tt MACH_MSG_TYPE_PORT_RECEIVE}
\end{itemize}
\end{itemize}}
\vfill
{\tiny\begin{code}
subsystem example 36270;

routine portdemo(
                server  : mach_port_t;
        in      arg1    : mach_port_t =
                                MACH_MSG_TYPE_PORT_SEND;
        out     arg2    : mach_port_t =
                                MACH_MSG_TYPE_PORT_SEND_ONCE;
        in      arg3    : mach_port_t =
                                MACH_MSG_TYPE_MOVE_RECEIVE);
\end{code}}
\end{slide}

\begin{slide}{}
\pagetitle{Port Arguments}
Client call:
{\tiny\begin{code}
#include "example.h"

    mach_port_t server;
    mach_port_t arg1, arg2, arg3;
    kern_return_t kr;

    kr = portdemo(server, arg1, MACH_MSG_TYPE_MOVE_SEND,
                  &arg2, arg3);
\end{code}}
Server function:
{\tiny\begin{code}
kern_return_t portdemo(server, arg1, arg2, arg2type, arg3)
    mach_port_t server;
    mach_port_t arg1;                   /* in */
    mach_port_t *arg2;                  /* out */
    mach_msg_type_name_t *arg2type;     /* out */
    mach_port_t arg3;                   /* in */
{
    /* dispose of the port rights we received */
    if (MACH_PORT_VALID(arg1))
        (void) mach_port_deallocate(mach_task_self(), arg1);
    if (MACH_PORT_VALID(arg3))
        (void) mach_port_mod_refs(mach_task_self(), arg3,
                                MACH_PORT_RIGHT_RECEIVE, -1);
    /* return a send-once right to the server port */
    *arg2 = server;
    *arg2type = MACH_MSG_TYPE_MAKE_SEND_ONCE;
    return KERN_SUCCESS;
}
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Pseudo-Arguments}
{\tiny\begin{code}
subsystem example 36270;
#include <mach/std_types.defs>

ServerPrefix do_;

/* give the server the reply port and sequence number
   from the request message header */

routine pseudodemo(
                server  : mach_port_t;
        SReplyPort reply: mach_port_t =
                                MACH_MSG_TYPE_MAKE_SEND_ONCE;
        MsgSeqno seqno  : mach_port_seqno_t;
        in      realarg : int);
\end{code}}
Client call:
{\tiny\begin{code}
    mach_port_t server;

    kr = pseudodemo(server, 10);
\end{code}}
Server function:
{\tiny\begin{code}
kern_return_t do_pseudodemo(server, reply, seqno, realarg)
    mach_port_t server;
    mach_port_t reply;
    mach_port_seqno_t seqno;
    int realarg;
{
    printf("Received %d.\n", realarg);
    return KERN_SUCCESS;
}
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Choosing Subsystem Ranges}
{\tiny\begin{code}
subsystem <name> <msgid>;

/* request msg is <msgid>, reply is <msgid> + 100 */
routine first( ... );

skip; /* skip <msgid> + 1 */

/* request msg is <msgid> + 2, reply is <msgid> + 102 */
routine second( ... );
\end{code}}
\vspace*{1in}
{\small\begin{itemize}
\item For binary compatibility, MsgIDs and real in/out arguments
should be preserved.
\item MsgID ranges handled by a single server should not overlap.
\item Helpful but not essential to keep interfaces under 100 routines.
\end{itemize}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Message Layout}
{\tiny\begin{code}
/* file example.defs */

subsystem example 36270;

#include <mach/std_types.defs>

routine layoutdemo(
                server  : mach_port_t;
        in      arg1    : int;
        out     arg2    : int;
        inout   arg3    : int);

/* from file exampleUser.c */

typedef struct {
        mach_msg_header_t Head;
        mach_msg_type_t arg1Type;
        int arg1;
        mach_msg_type_t arg3Type;
        int arg3;
} Request;

typedef struct {
        mach_msg_header_t Head;
        mach_msg_type_t RetCodeType;
        kern_return_t RetCode;
        mach_msg_type_t arg2Type;
        int arg2;
        mach_msg_type_t arg3Type;
        int arg3;
} Reply;
\end{code}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Server Loop}
\begin{interface}
\command{kern_return_t mach_msg_server(demux, max_size, rcv_name)}
Given the name of a port or port set, loops receiving request messages
and sending replies.  Uses Mig-generated demux functions to process
request messages and generate replies.  Needs maximum size
for request and reply messages.

\command{boolean_t demux(request-msg, reply-msg)}
Returns TRUE if this demux function processed the request.
In any case, must initialize the reply message.
\end{interface}

Desired properties:
{\small\begin{itemize}
\item Uses RPC form of {\tt mach_msg} for performance.
\item Doesn't leak port rights or memory regions.
\end{itemize}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Consume-On-Success}

What happens to resources like port rights and out-of-line memory
in request messages?

\begin{itemize}
\item The server function is responsible, \\ {\em if} it returns success.
\end{itemize}

What happens to resources in reply messages?

\begin{itemize}
\item {\tt mach_msg_server} is responsible.  A server function
should only produce outgoing resources when it returns success.
\end{itemize}

Return code from asynchronous server functions is important!
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Mig Hints}
{\small\begin{itemize}
\item Asynchronous messages not recommended.
\item InOut arguments not recommended.
\item Put type declarations in a separate file.
\item Use ServerPrefix.
\item Use polymorphic port types.
\item Use dynamic dealloc flag.
\end{itemize}}
\vfill
\end{slide}

\begin{slide}{}
\pagetitle{Mig Problems}
\begin{itemize}
\item Confusion between interface and implementation.
\item Only open-coded stubs, no descriptor-based stubs.
\item Nits:
\begin{itemize}
\item Message size information not exported.
\item Demultiplexing multiple interfaces.
\item MsgID assignment.
\end{itemize}
\end{itemize}
\end{slide}
