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