|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.