|
|
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.