Annotation of Gnu-Mach/mig/routine.h, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: 
                     27: #ifndef        _ROUTINE_H
                     28: #define        _ROUTINE_H
                     29: 
                     30: #include <sys/types.h>
                     31: 
                     32: #include "boolean.h"
                     33: #include "type.h"
                     34: 
                     35: /* base kind arg */
                     36: #define akeNone                (0)
                     37: #define akeNormal      (1)     /* a normal, user-defined argument */
                     38: #define akeRequestPort (2)     /* pointed at by rtRequestPort */
                     39: #define akeWaitTime    (3)     /* pointed at by rtWaitTime */
                     40: #define akeReplyPort   (4)     /* pointed at by rtReplyPort */
                     41: #define akeMsgOption   (5)     /* pointed at by rtMsgOption */
                     42: #define akeMsgSeqno    (6)     /* pointed at by rtMsgSeqno */
                     43: #define akeRetCode     (7)     /* pointed at by rtRetCode/rtReturn */
                     44: #define akeReturn      (8)     /* pointed at by rtReturn */
                     45: #define akeCount       (9)     /* a count arg for argParent */
                     46: #define akePoly                (10)    /* a poly arg for argParent */
                     47: #define        akeDealloc      (11)    /* a deallocate arg for argParent */
                     48: #define        akeServerCopy   (12)    /* a server-copy arg for argParent */
                     49: #define akeCountInOut  (13)    /* a count-in-out arg */
                     50: 
                     51: #define        akeBITS         (0x0000003f)
                     52: #define        akbRequest      (0x00000040)    /* has a msg_type in request */
                     53: #define        akbReply        (0x00000080)    /* has a msg_type in reply */
                     54: #define        akbUserArg      (0x00000100)    /* an arg on user-side */
                     55: #define        akbServerArg    (0x00000200)    /* an arg on server-side  */
                     56: #define akbSend                (0x00000400)    /* value carried in request */
                     57: #define akbSendBody    (0x00000800)    /* value carried in request body */
                     58: #define akbSendSnd     (0x00001000)    /* value stuffed into request */
                     59: #define akbSendRcv     (0x00002000)    /* value grabbed from request */
                     60: #define akbReturn      (0x00004000)    /* value carried in reply */
                     61: #define akbReturnBody  (0x00008000)    /* value carried in reply body */
                     62: #define akbReturnSnd   (0x00010000)    /* value stuffed into reply */
                     63: #define akbReturnRcv   (0x00020000)    /* value grabbed from reply */
                     64: #define akbReplyInit   (0x00040000)    /* reply msg-type must be init'ed */
                     65: #define akbRequestQC   (0x00080000)    /* msg_type can be checked quickly */
                     66: #define akbReplyQC     (0x00100000)    /* msg_type can be checked quickly */
                     67: #define akbReplyCopy   (0x00200000)    /* copy reply value from request */
                     68: #define akbVarNeeded   (0x00400000)    /* may need local var in server */
                     69: #define akbDestroy     (0x00800000)    /* call destructor function */
                     70: #define akbVariable    (0x01000000)    /* variable size inline data */
                     71: #define        akbIndefinite   (0x02000000)    /* variable size, inline or out */
                     72: #define        akbPointer      (0x04000000)    /* server gets a pointer to the
                     73:                                           real buffer */
                     74: /* be careful, there aren't many bits left */
                     75: 
                     76: typedef u_int  arg_kind_t;
                     77: 
                     78: /*
                     79:  * akbRequest means msg_type/data fields are allocated in the request
                     80:  * msg.  akbReply means msg_type/data fields are allocated in the
                     81:  * reply msg.  These bits (with akbReplyInit, akbRequestQC, akbReplyQC)
                     82:  * control msg structure declarations packing, and checking of
                     83:  * mach_msg_type_t fields.
                     84:  *
                     85:  * akbUserArg means this argument is an argument to the user-side stub.
                     86:  * akbServerArg means this argument is an argument to
                     87:  * the server procedure called by the server-side stub.
                     88:  *
                     89:  * The akbSend* and akbReturn* bits control packing/extracting values
                     90:  * in the request and reply messages.
                     91:  *
                     92:  * akbSend means the argument's value is carried in the request msg.
                     93:  * akbSendBody implies akbSend; the value is carried in the msg body.
                     94:  * akbSendSnd implies akbSend; the value is stuffed into the request.
                     95:  * akbSendRcv implies akbSend; the value is pulled out of the request.
                     96:  *
                     97:  * akbReturn, akbReturnBody, akbReturnSnd, akbReturnRcv are defined
                     98:  * similarly but apply to the reply message.
                     99:  *
                    100:  * User-side code generation (header.c, user.c) and associated code
                    101:  * should use akbSendSnd and akbReturnRcv, but not akbSendRcv and
                    102:  * akbReturnSnd.  Server-side code generation (server.c) is reversed.
                    103:  * Code generation should use the more specific akb{Send,Return}{Snd,Rcv}
                    104:  * bits when possible, instead of akb{Send,Return}.
                    105:  *
                    106:  * Note that akRetCode and akReturn lack any Return bits, although
                    107:  * there is a value in the msg.  These guys are packed/unpacked
                    108:  * with special code, unlike other arguments.
                    109:  *
                    110:  * akbReplyInit implies akbReply.  It means the server-side stub
                    111:  * should initialize the argument's msg_type field in the reply msg.
                    112:  * Some special arguments (RetCode, Dummy, Tid) have their msg_type
                    113:  * fields in the reply message initialized by the server demux
                    114:  * function; these arguments have akbReply but not akbReplyInit.
                    115:  *
                    116:  * akbRequestQC implies akbRequest.  If it's on, then the
                    117:  * mach_msg_type_t value in the request message can be checked quickly
                    118:  * (by casting to an int and checking with a single comparison).
                    119:  * akbReplyQC has the analogous meaning with respect to akbReply.
                    120:  *
                    121:  * akbVariable means the argument has variable-sized inline data.
                    122:  * It isn't currently used for code generation, but routine.c
                    123:  * does use it internally.  It is added in rtAugmentArgKind.
                    124:  *
                    125:  * akbReplyCopy and akbVarNeeded help control code generation in the
                    126:  * server-side stub.  The preferred method of handling data in the
                    127:  * server-side stub avoids copying into/out-of local variables.  In
                    128:  * arguments get passed directly to the server proc from the request msg.
                    129:  * Out arguments get stuffed directly into the reply msg by the server proc.
                    130:  * For InOut arguments, the server proc gets the address of the data in
                    131:  * the request msg, and the resulting data gets copied to the reply msg.
                    132:  * Some arguments need a local variable in the server-side stub.  The
                    133:  * code extracts the data from the request msg into the variable, and
                    134:  * stuff the reply msg from the variable.
                    135:  *
                    136:  * akbReplyCopy implies akbReply.  It means the data should get copied
                    137:  * from the request msg to the reply msg after the server proc is called.
                    138:  * It is only used by akInOut.  akTid doesn't need it because the tid
                    139:  * data in the reply msg is initialized in the server demux function.
                    140:  *
                    141:  * akbVarNeeded means the argument needs a local variable in the
                    142:  * server-side stub.  It is added in rtAugmentArgKind and
                    143:  * rtCheckVariable.  An argument shouldn't have all three of
                    144:  * akbReturnSnd, akbVarNeeded and akbReplyCopy, because this indicates
                    145:  * the reply msg should be stuffed both ways.
                    146:  *
                    147:  * akbDestroy helps control code generation in the server-side stub.
                    148:  * It means this argument has a destructor function which should be called.
                    149:  *
                    150:  * Header file generation (header.c) uses:
                    151:  *     akbUserArg
                    152:  *
                    153:  * User stub generation (user.c) uses:
                    154:  *     akbUserArg, akbRequest, akbReply, akbSendSnd,
                    155:  *     akbSendBody, akbReturnRcv, akbReplyQC
                    156:  *
                    157:  * Server stub generation (server.c) uses:
                    158:  *     akbServerArg, akbRequest, akbReply, akbSendRcv, akbReturnSnd,
                    159:  *     akbReplyInit, akbReplyCopy, akbVarNeeded, akbSendBody, akbRequestQC
                    160:  *
                    161:  *
                    162:  * During code generation, the routine, argument, and type data structures
                    163:  * are read-only.  The code generation functions' output is their only
                    164:  * side-effect.
                    165:  *
                    166:  *
                    167:  * Style note:
                    168:  * Code can use logical operators (|, &, ~) on akb values.
                    169:  * ak values should be manipulated with the ak functions.
                    170:  */
                    171: 
                    172: /* various useful combinations */
                    173: 
                    174: #define akbNone                (0)
                    175: #define akbAll         (~akbNone)
                    176: #define akbAllBits     (~akeBITS)
                    177: 
                    178: #define akbSendBits    (akbSend|akbSendBody|akbSendSnd|akbSendRcv)
                    179: #define akbReturnBits  (akbReturn|akbReturnBody|akbReturnSnd|akbReturnRcv)
                    180: #define akbSendReturnBits      (akbSendBits|akbReturnBits)
                    181: 
                    182: #define akNone         akeNone
                    183: 
                    184: #define akIn           akAddFeature(akeNormal,                         \
                    185:        akbUserArg|akbServerArg|akbRequest|akbSendBits)
                    186: 
                    187: #define akOut          akAddFeature(akeNormal,                         \
                    188:        akbUserArg|akbServerArg|akbReply|akbReturnBits|akbReplyInit)
                    189: 
                    190: #define akInOut                akAddFeature(akeNormal,                         \
                    191:        akbUserArg|akbServerArg|akbRequest|akbReply|                    \
                    192:        akbSendBits|akbReturnBits|akbReplyInit|akbReplyCopy)
                    193: 
                    194: #define akRequestPort  akAddFeature(akeRequestPort,                    \
                    195:        akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv)
                    196: 
                    197: #define akWaitTime     akAddFeature(akeWaitTime, akbUserArg)
                    198: 
                    199: #define akMsgOption    akAddFeature(akeMsgOption, akbUserArg)
                    200: 
                    201: #define akMsgSeqno     akAddFeature(akeMsgSeqno,                       \
                    202:        akbServerArg|akbSend|akbSendRcv)
                    203: 
                    204: #define akReplyPort    akAddFeature(akeReplyPort,                      \
                    205:        akbUserArg|akbServerArg|akbSend|akbSendSnd|akbSendRcv)
                    206: 
                    207: #define akUReplyPort   akAddFeature(akeReplyPort,                      \
                    208:        akbUserArg|akbSend|akbSendSnd|akbSendRcv)
                    209: 
                    210: #define akSReplyPort   akAddFeature(akeReplyPort,                      \
                    211:        akbServerArg|akbSend|akbSendSnd|akbSendRcv)
                    212: 
                    213: #define akRetCode      akAddFeature(akeRetCode, akbReply)
                    214: 
                    215: #define akReturn       akAddFeature(akeReturn,                         \
                    216:        akbReply|akbReplyInit)
                    217: 
                    218: #define akCount                akAddFeature(akeCount,                          \
                    219:        akbUserArg|akbServerArg)
                    220: 
                    221: #define akPoly         akePoly
                    222: 
                    223: #define        akDealloc       akAddFeature(akeDealloc, akbUserArg)
                    224: 
                    225: #define        akServerCopy    akAddFeature(akeServerCopy, akbServerArg|akbSendRcv)
                    226: 
                    227: #define akCountInOut   akAddFeature(akeCountInOut, akbRequest|akbSendBits)
                    228: 
                    229: #define        akCheck(ak, bits)       ((ak) & (bits))
                    230: #define akCheckAll(ak, bits)   (akCheck(ak, bits) == (bits))
                    231: #define akAddFeature(ak, bits) ((ak)|(bits))
                    232: #define akRemFeature(ak, bits) ((ak)&~(bits))
                    233: #define akIdent(ak)            ((ak) & akeBITS)
                    234: 
                    235: /*
                    236:  * The arguments to a routine/function are linked in left-to-right order.
                    237:  * argName is used for error messages and pretty-printing,
                    238:  * not code generation.  Code generation shouldn't make any assumptions
                    239:  * about the order of arguments, esp. count and poly arguments.
                    240:  * (Unfortunately, code generation for inline variable-sized arguments
                    241:  * does make such assumptions.)
                    242:  *
                    243:  * argVarName is the name used in generated code for function arguments
                    244:  * and local variable names.  argMsgField is the name used in generated
                    245:  * code for the field in msgs where the argument's value lives.
                    246:  * argTTName is the name used in generated code for msg-type fields and
                    247:  * static variables used to initialize those fields.  argPadName is the
                    248:  * name used in generated code for a padding field in msgs.
                    249:  *
                    250:  * argFlags can be used to override the deallocate and longform bits
                    251:  * in the argument's type.  rtProcessArgFlags sets argDeallocate and
                    252:  * argLongForm from it and the type.  Code generation shouldn't use
                    253:  * argFlags.
                    254:  *
                    255:  * argCount, argPoly, and argDealloc get to the implicit count, poly,
                    256:  * and dealloc arguments associated with the argument; they should be
                    257:  * used instead of argNext.  In these implicit arguments, argParent is
                    258:  * a pointer to the "real" arg.
                    259:  *
                    260:  * In count arguments, argMultiplier is a scaling factor applied to
                    261:  * the count arg's value to get msg-type-number.  It is equal to
                    262:  *     argParent->argType->itElement->itNumber
                    263:  */
                    264: 
                    265: typedef struct argument
                    266: {
                    267:     /* if argKind == akReturn, then argName is name of the function */
                    268:     identifier_t argName;
                    269:     struct argument *argNext;
                    270: 
                    271:     arg_kind_t argKind;
                    272:     ipc_type_t *argType;
                    273: 
                    274:     const_string_t argVarName; /* local variable and argument names */
                    275:     const_string_t argMsgField;        /* message field's name */
                    276:     const_string_t argTTName;  /* name for msg_type fields, static vars */
                    277:     const_string_t argPadName; /* name for pad field in msg */
                    278: 
                    279:     ipc_flags_t argFlags;
                    280:     dealloc_t argDeallocate;   /* overrides argType->itDeallocate */
                    281:     boolean_t argLongForm;     /* overrides argType->itLongForm */
                    282:     boolean_t argServerCopy;
                    283:     boolean_t argCountInOut;
                    284: 
                    285:     struct routine *argRoutine;        /* routine we are part of */
                    286: 
                    287:     struct argument *argCount; /* our count arg, if present */
                    288:     struct argument *argCInOut;        /* our CountInOut arg, if present */
                    289:     struct argument *argPoly;  /* our poly arg, if present */
                    290:     struct argument *argDealloc;/* our dealloc arg, if present */
                    291:     struct argument *argSCopy; /* our serverCopy arg, if present */
                    292:     struct argument *argParent;        /* in a count or poly arg, the base arg */
                    293:     int argMultiplier;         /* for Count argument: parent is a multiple
                    294:                                   of a basic IPC type.  Argument must be
                    295:                                   multiplied by Multiplier to get IPC
                    296:                                   number-of-elements. */
                    297: 
                    298:     /* how variable/inline args precede this one, in request and reply */
                    299:     int argRequestPos;
                    300:     int argReplyPos;
                    301:     /* whether argument is by reference, on user and server side */
                    302:     boolean_t  argByReferenceUser;
                    303:     boolean_t  argByReferenceServer;
                    304: } argument_t;
                    305: 
                    306: /*
                    307:  * The various routine kinds' peculiarities are abstracted by rtCheckRoutine
                    308:  * into attributes like rtOneWay, rtProcedure, etc.  These are what
                    309:  * code generation should use.  It is Bad Form for code generation to
                    310:  * test rtKind.
                    311:  */
                    312: 
                    313: typedef enum
                    314: {
                    315:     rkRoutine,
                    316:     rkSimpleRoutine,
                    317:     rkSimpleProcedure,
                    318:     rkProcedure,
                    319:     rkFunction,
                    320: } routine_kind_t;
                    321: 
                    322: typedef struct routine
                    323: {
                    324:     identifier_t rtName;
                    325:     routine_kind_t rtKind;
                    326:     argument_t *rtArgs;
                    327:     u_int rtNumber;            /* used for making msg ids */
                    328: 
                    329:     identifier_t rtUserName;   /* user-visible name (UserPrefix + Name) */
                    330:     identifier_t rtServerName; /* server-side name (ServerPrefix + Name) */
                    331: 
                    332:     /* rtErrorName is only used for Procs, SimpleProcs, & Functions */
                    333:     identifier_t rtErrorName;  /* error-handler name */
                    334: 
                    335:     boolean_t rtOneWay;                /* SimpleProcedure or SimpleRoutine */
                    336:     boolean_t rtProcedure;     /* Procedure or SimpleProcedure */
                    337:     boolean_t rtUseError;      /* Procedure or Function */
                    338: 
                    339:     boolean_t rtSimpleFixedRequest;    /* fixed msg-simple value in request */
                    340:     boolean_t rtSimpleSendRequest;     /* in any case, initial value */
                    341:     boolean_t rtSimpleCheckRequest;    /* check msg-simple in request */
                    342:     boolean_t rtSimpleReceiveRequest;  /* if so, the expected value */
                    343: 
                    344:     boolean_t rtSimpleFixedReply;      /* fixed msg-simple value in reply */
                    345:     boolean_t rtSimpleSendReply;       /* in any case, initial value */
                    346:     boolean_t rtSimpleCheckReply;      /* check msg-simple in reply */
                    347:     boolean_t rtSimpleReceiveReply;    /* if so, the expected value */
                    348: 
                    349:     u_int rtRequestSize;       /* minimal size of a legal request msg */
                    350:     u_int rtReplySize;         /* minimal size of a legal reply msg */
                    351: 
                    352:     int rtNumRequestVar;       /* number of variable/inline args in request */
                    353:     int rtNumReplyVar;         /* number of variable/inline args in reply */
                    354: 
                    355:     int rtMaxRequestPos;       /* maximum of argRequestPos */
                    356:     int rtMaxReplyPos;         /* maximum of argReplyPos */
                    357: 
                    358:     boolean_t rtNoReplyArgs;   /* if so, no reply message arguments beyond
                    359:                                   what the server dispatch routine inserts */
                    360: 
                    361:     /* distinguished arguments */
                    362:     argument_t *rtRequestPort; /* always non-NULL, defaults to first arg */
                    363:     argument_t *rtUReplyPort;  /* always non-NULL, defaults to Mig-supplied */
                    364:     argument_t *rtSReplyPort;  /* always non-NULL, defaults to Mig-supplied */
                    365:     argument_t *rtReturn;      /* non-NULL unless rtProcedure */
                    366:     argument_t *rtServerReturn;        /* NULL or rtReturn  */
                    367:     argument_t *rtRetCode;     /* always non-NULL */
                    368:     argument_t *rtWaitTime;    /* if non-NULL, will use MACH_RCV_TIMEOUT */
                    369:     argument_t *rtMsgOption;   /* always non-NULL, defaults to NONE */
                    370:     argument_t *rtMsgSeqno;    /* if non-NULL, server gets passed seqno */
                    371: } routine_t;
                    372: 
                    373: #define rtNULL         ((routine_t *) 0)
                    374: #define argNULL                ((argument_t *) 0)
                    375: 
                    376: extern u_int rtNumber;
                    377: /* rt->rtNumber will be initialized */
                    378: extern routine_t *rtAlloc(void);
                    379: /* skip a number */
                    380: extern void rtSkip(int);
                    381: 
                    382: extern argument_t *argAlloc(void);
                    383: 
                    384: extern boolean_t rtCheckMask(const argument_t *args, u_int mask);
                    385: 
                    386: extern boolean_t rtCheckMaskFunction(const argument_t *args, u_int mask,
                    387:                                     boolean_t (*func)(const argument_t *arg));
                    388: 
                    389: extern routine_t *rtMakeRoutine(identifier_t name, argument_t *args);
                    390: extern routine_t *rtMakeSimpleRoutine(identifier_t name, argument_t *args);
                    391: extern routine_t *rtMakeProcedure(identifier_t name, argument_t *args);
                    392: extern routine_t *rtMakeSimpleProcedure(identifier_t name, argument_t *args);
                    393: extern routine_t *rtMakeFunction(identifier_t name, argument_t *args,
                    394:                                 ipc_type_t *type);
                    395: 
                    396: extern void rtPrintRoutine(const routine_t *rt);
                    397: extern void rtCheckRoutine(routine_t *rt);
                    398: 
                    399: extern const char *rtRoutineKindToStr(routine_kind_t rk);
                    400: 
                    401: #endif /* _ROUTINE_H */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.