|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50: /*
51: */
52: /*
53: * File: ipc/ipc_kmsg.h
54: * Author: Rich Draves
55: * Date: 1989
56: *
57: * Definitions for kernel messages.
58: */
59:
60: #ifndef _IPC_IPC_KMSG_H_
61: #define _IPC_IPC_KMSG_H_
62:
63: #include <cpus.h>
64: #include <dipc.h>
65: #include <mach_rt.h>
66:
67: #include <mach/vm_types.h>
68: #include <mach/message.h>
69: #include <kern/assert.h>
70: #include <kern/cpu_number.h>
71: #include <kern/macro_help.h>
72: #include <kern/kalloc.h>
73: #if MACH_RT
74: #include <kern/rtmalloc.h>
75: #endif /* MACH_RT */
76: #include <ipc/ipc_object.h>
77:
78: #if DIPC
79: #include <dipc/dipc_types.h> /* for handle_t definition */
80: #endif /* DIPC */
81:
82: /*
83: * This structure is only the header for a kmsg buffer;
84: * the actual buffer is normally larger. The rest of the buffer
85: * holds the body of the message.
86: *
87: * In a kmsg, the port fields hold pointers to ports instead
88: * of port names. These pointers hold references.
89: *
90: * The ikm_header.msgh_remote_port field is the destination
91: * of the message.
92: */
93:
94: #if DIPC
95: /*
96: * Refer to dipc/dipc_kmsg.h for a description of the
97: * meta_kmsg, a placeholder used to enqueue sufficient
98: * information about a kmsg to retrieve it from a
99: * remote sender. Also look in that file for a description
100: * of the changes in use of certain kmsg fields during
101: * the DIPC receiving process.
102: *
103: * The ikm_handle links the local kmsg (or meta_kmsg) to
104: * the remote sender's kmsg. Unfortunately, it just isn't
105: * possible to overload one of the kmsg fields with the
106: * handle. We can't overload the next and prev pointers
107: * or the ikm_size field because this information is all
108: * needed while the message is enqueued. The size in the
109: * message header could be stolen but not easily: then it
110: * is difficult to have a queued, inline kmsg that still
111: * has remote components.
112: */
113: #endif /* DIPC */
114:
115: typedef struct ipc_kmsg {
116: struct ipc_kmsg *ikm_next, *ikm_prev;
117: vm_size_t ikm_size;
118: vm_offset_t ikm_private; /* allocator-private info */
119: #if DIPC
120: handle_t ikm_handle;
121: #endif /* DIPC */
122: mach_msg_header_t ikm_header;
123: } *ipc_kmsg_t;
124:
125: #define IKM_NULL ((ipc_kmsg_t) 0)
126:
127: #define IKM_OVERHEAD \
128: (sizeof(struct ipc_kmsg) - sizeof(mach_msg_header_t))
129:
130: #define ikm_plus_overhead(size) ((vm_size_t)((size) + IKM_OVERHEAD))
131: #define ikm_less_overhead(size) ((mach_msg_size_t)((size) - IKM_OVERHEAD))
132:
133: /*
134: * XXX For debugging.
135: */
136: #define IKM_BOGUS ((ipc_kmsg_t) 0xffffff10)
137:
138: /*
139: * The size of the kernel message buffers that will be cached.
140: * IKM_SAVED_KMSG_SIZE includes overhead; IKM_SAVED_MSG_SIZE doesn't.
141: */
142:
143: #define IKM_SAVED_KMSG_SIZE ((vm_size_t) 256)
144: #define IKM_SAVED_MSG_SIZE ikm_less_overhead(IKM_SAVED_KMSG_SIZE)
145:
146: #define ikm_alloc(size) \
147: ((ipc_kmsg_t) kalloc(ikm_plus_overhead(size)))
148:
149: #if MACH_RT
150:
151: #define ikm_rtalloc(size) \
152: ((ipc_kmsg_t) rtmalloc(ikm_plus_overhead(size)))
153:
154: #define KMSG_IS_RT(kmsg) \
155: ((kmsg)->ikm_header.msgh_bits & MACH_MSGH_BITS_RTALLOC)
156: #define KMSG_MARK_RT(kmsg) \
157: ((kmsg)->ikm_header.msgh_bits |= MACH_MSGH_BITS_RTALLOC)
158:
159: #else /* MACH_RT */
160:
161: /*
162: * It's legal to ask whether a kmsg is RT-related even
163: * in a non-RT kernel configuration. The answer is always no.
164: * But note that it's NOT legal to try to do KMSG_MARK_RT
165: * in a non-RT kernel configuration.
166: */
167: #define KMSG_IS_RT(kmsg) 0
168:
169: #endif /* MACH_RT */
170:
171: #define ikm_init(kmsg, size) \
172: MACRO_BEGIN \
173: ikm_init_special((kmsg), ikm_plus_overhead(size)); \
174: MACRO_END
175:
176: #if DIPC
177: /*
178: * The msgh_bits must be initialized to zero so that
179: * the MACH_MSGH_BITS_META_KMSG flag is initialized
180: * to FALSE. This might be worth making the default
181: * for the non-DIPC case, too.
182: */
183: #define ikm_init_special(kmsg, size) \
184: MACRO_BEGIN \
185: (kmsg)->ikm_size = (size); \
186: (kmsg)->ikm_header.msgh_bits = 0; \
187: MACRO_END
188: #else /* !DIPC */
189: #define ikm_init_special(kmsg, size) \
190: MACRO_BEGIN \
191: (kmsg)->ikm_size = (size); \
192: MACRO_END
193: #endif /* DIPC */
194:
195: #define ikm_check_initialized(kmsg, size) \
196: MACRO_BEGIN \
197: assert((kmsg)->ikm_size == (size)); \
198: MACRO_END
199:
200: /*
201: * Non-positive message sizes are special. They indicate that
202: * the message buffer doesn't come from ikm_alloc and
203: * requires some special handling to free.
204: *
205: * ipc_kmsg_free is the non-macro form of ikm_free.
206: * It frees kmsgs of all varieties.
207: */
208:
209: #define IKM_SIZE_NETWORK -1
210: #define IKM_SIZE_INTR_KMSG -2
211:
212: #if MACH_RT
213:
214: #define ikm_free(kmsg) \
215: MACRO_BEGIN \
216: register vm_size_t _size = (kmsg)->ikm_size; \
217: \
218: if ((integer_t)_size > 0) \
219: if (KMSG_IS_RT(kmsg)) \
220: rtfree((vm_offset_t) (kmsg), _size); \
221: else \
222: kfree((vm_offset_t) (kmsg), _size); \
223: else \
224: ipc_kmsg_free(kmsg); \
225: MACRO_END
226:
227: #else /* MACH_RT */
228:
229: #define ikm_free(kmsg) \
230: MACRO_BEGIN \
231: register vm_size_t _size = (kmsg)->ikm_size; \
232: \
233: if ((integer_t)_size > 0) \
234: kfree((vm_offset_t) (kmsg), _size); \
235: else \
236: ipc_kmsg_free(kmsg); \
237: MACRO_END
238:
239: #endif /* MACH_RT */
240:
241:
242: struct ipc_kmsg_queue {
243: struct ipc_kmsg *ikmq_base;
244: };
245:
246: typedef struct ipc_kmsg_queue *ipc_kmsg_queue_t;
247:
248: #define IKMQ_NULL ((ipc_kmsg_queue_t) 0)
249:
250:
251: /*
252: * Exported interfaces
253: */
254:
255: #define ipc_kmsg_queue_init(queue) \
256: MACRO_BEGIN \
257: (queue)->ikmq_base = IKM_NULL; \
258: MACRO_END
259:
260: #define ipc_kmsg_queue_empty(queue) ((queue)->ikmq_base == IKM_NULL)
261:
262: /* Enqueue a kmsg */
263: extern void ipc_kmsg_enqueue(
264: ipc_kmsg_queue_t queue,
265: ipc_kmsg_t kmsg);
266:
267: /* Dequeue and return a kmsg */
268: extern ipc_kmsg_t ipc_kmsg_dequeue(
269: ipc_kmsg_queue_t queue);
270:
271: /* Pull a kmsg out of a queue */
272: extern void ipc_kmsg_rmqueue(
273: ipc_kmsg_queue_t queue,
274: ipc_kmsg_t kmsg);
275:
276: #define ipc_kmsg_queue_first(queue) ((queue)->ikmq_base)
277:
278: /* Return the kmsg following the given kmsg */
279: extern ipc_kmsg_t ipc_kmsg_queue_next(
280: ipc_kmsg_queue_t queue,
281: ipc_kmsg_t kmsg);
282:
283: #define ipc_kmsg_rmqueue_first_macro(queue, kmsg) \
284: MACRO_BEGIN \
285: register ipc_kmsg_t _next; \
286: \
287: assert((queue)->ikmq_base == (kmsg)); \
288: \
289: _next = (kmsg)->ikm_next; \
290: if (_next == (kmsg)) { \
291: assert((kmsg)->ikm_prev == (kmsg)); \
292: (queue)->ikmq_base = IKM_NULL; \
293: } else { \
294: register ipc_kmsg_t _prev = (kmsg)->ikm_prev; \
295: \
296: (queue)->ikmq_base = _next; \
297: _next->ikm_prev = _prev; \
298: _prev->ikm_next = _next; \
299: } \
300: /* XXX Debug paranoia */ \
301: kmsg->ikm_next = IKM_BOGUS; \
302: kmsg->ikm_prev = IKM_BOGUS; \
303: MACRO_END
304:
305: #define ipc_kmsg_enqueue_macro(queue, kmsg) \
306: MACRO_BEGIN \
307: register ipc_kmsg_t _first = (queue)->ikmq_base; \
308: \
309: if (_first == IKM_NULL) { \
310: (queue)->ikmq_base = (kmsg); \
311: (kmsg)->ikm_next = (kmsg); \
312: (kmsg)->ikm_prev = (kmsg); \
313: } else { \
314: register ipc_kmsg_t _last = _first->ikm_prev; \
315: \
316: (kmsg)->ikm_next = _first; \
317: (kmsg)->ikm_prev = _last; \
318: _first->ikm_prev = (kmsg); \
319: _last->ikm_next = (kmsg); \
320: } \
321: MACRO_END
322:
323: /* scatter list macros */
324:
325: #define SKIP_PORT_DESCRIPTORS(s, e) \
326: MACRO_BEGIN \
327: if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
328: while ((s) < (e)) { \
329: if ((s)->type.type != MACH_MSG_PORT_DESCRIPTOR) \
330: break; \
331: (s)++; \
332: } \
333: if ((s) >= (e)) \
334: (s) = MACH_MSG_DESCRIPTOR_NULL; \
335: } \
336: MACRO_END
337:
338: #define INCREMENT_SCATTER(s) \
339: MACRO_BEGIN \
340: if ((s) != MACH_MSG_DESCRIPTOR_NULL) { \
341: (s)++; \
342: } \
343: MACRO_END
344:
345: /*
346: * extern void
347: * ipc_kmsg_send_always(ipc_kmsg_t);
348: *
349: * Unfortunately, to avoid warnings/lint about unused variables
350: * when assertions are turned off, we need two versions of this.
351: */
352: #if MACH_ASSERT
353:
354: #define ipc_kmsg_send_always(kmsg) \
355: MACRO_BEGIN \
356: mach_msg_return_t mr; \
357: \
358: mr = ipc_kmsg_send((kmsg), MACH_SEND_ALWAYS, \
359: MACH_MSG_TIMEOUT_NONE); \
360: assert(mr == MACH_MSG_SUCCESS); \
361: MACRO_END
362:
363: #else /* MACH_ASSERT */
364:
365: #define ipc_kmsg_send_always(kmsg) \
366: MACRO_BEGIN \
367: (void) ipc_kmsg_send((kmsg), MACH_SEND_ALWAYS, \
368: MACH_MSG_TIMEOUT_NONE); \
369: MACRO_END
370:
371: #endif /* MACH_ASSERT */
372:
373: /* Destroy kernel message */
374: extern void ipc_kmsg_destroy(
375: ipc_kmsg_t kmsg);
376:
377: /* Free a kernel message buffer */
378: extern void ipc_kmsg_free(
379: ipc_kmsg_t kmsg);
380:
381: /* Allocate a kernel message buffer and copy a user message to the buffer */
382: extern mach_msg_return_t ipc_kmsg_get(
383: mach_msg_header_t *msg,
384: mach_msg_size_t size,
385: ipc_kmsg_t *kmsgp,
386: ipc_space_t space);
387:
388: /* Allocate a kernel message buffer and copy a kernel message to the buffer */
389: extern mach_msg_return_t ipc_kmsg_get_from_kernel(
390: mach_msg_header_t *msg,
391: mach_msg_size_t size,
392: ipc_kmsg_t *kmsgp);
393:
394: /* Send a message to a port */
395: extern mach_msg_return_t ipc_kmsg_send(
396: ipc_kmsg_t kmsg,
397: mach_msg_option_t option,
398: mach_msg_timeout_t timeout);
399:
400: /* Copy a kernel message buffer to a user message */
401: extern mach_msg_return_t ipc_kmsg_put(
402: mach_msg_header_t *msg,
403: ipc_kmsg_t kmsg,
404: mach_msg_size_t size);
405:
406: /* Copy a kernel message buffer to a kernel message */
407: extern void ipc_kmsg_put_to_kernel(
408: mach_msg_header_t *msg,
409: ipc_kmsg_t kmsg,
410: mach_msg_size_t size);
411:
412: /* Copyin port rights in the header of a message */
413: extern mach_msg_return_t ipc_kmsg_copyin_header(
414: mach_msg_header_t *msg,
415: ipc_space_t space,
416: mach_port_name_t notify);
417:
418: /* Copyin port rights and out-of-line memory from a user message */
419: extern mach_msg_return_t ipc_kmsg_copyin(
420: ipc_kmsg_t kmsg,
421: ipc_space_t space,
422: vm_map_t map,
423: mach_port_name_t notify);
424:
425: /* Copyin port rights and out-of-line memory from a kernel message */
426: extern void ipc_kmsg_copyin_from_kernel(
427: ipc_kmsg_t kmsg);
428:
429: /* Copyout port rights in the header of a message */
430: extern mach_msg_return_t ipc_kmsg_copyout_header(
431: mach_msg_header_t *msg,
432: ipc_space_t space,
433: mach_port_name_t notify);
434:
435: /* Copyout a port right returning a name */
436: extern mach_msg_return_t ipc_kmsg_copyout_object(
437: ipc_space_t space,
438: ipc_object_t object,
439: mach_msg_type_name_t msgt_name,
440: mach_port_name_t *namep);
441:
442: /* Copyout the header and body to a user message */
443: extern mach_msg_return_t ipc_kmsg_copyout(
444: ipc_kmsg_t kmsg,
445: ipc_space_t space,
446: vm_map_t map,
447: mach_port_name_t notify,
448: mach_msg_body_t *slist);
449:
450: /* Copyout port rights and out-of-line memory from the body of a message */
451: extern mach_msg_return_t ipc_kmsg_copyout_body(
452: ipc_kmsg_t kmsg,
453: ipc_space_t space,
454: vm_map_t map,
455: mach_msg_body_t *slist);
456:
457: /* Copyout port rights and out-of-line memory to a user message,
458: not reversing the ports in the header */
459: extern mach_msg_return_t ipc_kmsg_copyout_pseudo(
460: ipc_kmsg_t kmsg,
461: ipc_space_t space,
462: vm_map_t map,
463: mach_msg_body_t *slist);
464:
465: /* Copyout the destination port in the message */
466: extern void ipc_kmsg_copyout_dest(
467: ipc_kmsg_t kmsg,
468: ipc_space_t space);
469:
470: /* kernel's version of ipc_kmsg_copyout_dest */
471: extern void ipc_kmsg_copyout_to_kernel(
472: ipc_kmsg_t kmsg,
473: ipc_space_t space);
474:
475: /* Check scatter and gather lists for consistency */
476: extern mach_msg_return_t ipc_kmsg_check_scatter(
477: ipc_kmsg_t kmsg,
478: mach_msg_option_t option,
479: mach_msg_body_t **slistp,
480: mach_msg_size_t *sizep);
481:
482: extern boolean_t ikm_cache_get(
483: ipc_kmsg_t *kmsg);
484: extern boolean_t ikm_cache_put(
485: ipc_kmsg_t kmsg);
486:
487: #include <mach_kdb.h>
488: #if MACH_KDB
489:
490: /* Do a formatted dump of a kernel message */
491: extern void ipc_kmsg_print(
492: ipc_kmsg_t kmsg);
493:
494: /* Do a formatted dump of a user message */
495: extern void ipc_msg_print(
496: mach_msg_header_t *msgh);
497:
498: #endif /* MACH_KDB */
499:
500: #endif /* _IPC_IPC_KMSG_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.