Annotation of XNU/osfmk/ipc/ipc_kmsg.h, revision 1.1.1.1

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_ */

unix.superglobalmegacorp.com

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