Annotation of Gnu-Mach/kern/ipc_kobject.c, revision 1.1.1.4

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.2   root        5:  *
1.1       root        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.
1.1.1.2   root       11:  *
1.1       root       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.
1.1.1.2   root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.2   root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.2   root       22:  *
1.1       root       23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  */
                     28: /*
                     29:  *     File:   kern/ipc_kobject.c
                     30:  *     Author: Rich Draves
                     31:  *     Date:   1989
                     32:  *
                     33:  *     Functions for letting a port represent a kernel object.
                     34:  */
                     35: 
1.1.1.3   root       36: #include <kern/debug.h>
                     37: #include <kern/printf.h>
1.1       root       38: #include <mach/port.h>
                     39: #include <mach/kern_return.h>
                     40: #include <mach/message.h>
                     41: #include <mach/mig_errors.h>
                     42: #include <mach/notify.h>
                     43: #include <kern/ipc_kobject.h>
                     44: #include <ipc/ipc_object.h>
                     45: #include <ipc/ipc_kmsg.h>
                     46: #include <ipc/ipc_port.h>
                     47: #include <ipc/ipc_thread.h>
1.1.1.3   root       48: #include <vm/vm_object.h>
                     49: #include <vm/memory_object_proxy.h>
                     50: #include <device/ds_routines.h>
1.1       root       51: 
1.1.1.4 ! root       52: #include <kern/mach.server.h>
        !            53: #include <ipc/mach_port.server.h>
        !            54: #include <kern/mach_host.server.h>
        !            55: #include <device/device.server.h>
        !            56: #include <device/device_pager.server.h>
        !            57: #include <kern/mach4.server.h>
        !            58: #include <kern/gnumach.server.h>
        !            59: 
        !            60: #if MACH_DEBUG
        !            61: #include <kern/mach_debug.server.h>
        !            62: #endif
        !            63: 
1.1       root       64: #if    MACH_MACHINE_ROUTINES
                     65: #include <machine/machine_routines.h>
1.1.1.4 ! root       66: #include MACHINE_SERVER_HEADER
1.1       root       67: #endif
                     68: 
                     69: 
                     70: /*
                     71:  *     Routine:        ipc_kobject_server
                     72:  *     Purpose:
                     73:  *             Handle a message sent to the kernel.
                     74:  *             Generates a reply message.
                     75:  *     Conditions:
                     76:  *             Nothing locked.
                     77:  */
                     78: 
                     79: ipc_kmsg_t
                     80: ipc_kobject_server(request)
                     81:        ipc_kmsg_t request;
                     82: {
                     83:        mach_msg_size_t reply_size = ikm_less_overhead(8192);
                     84:        ipc_kmsg_t reply;
                     85:        kern_return_t kr;
                     86:        mig_routine_t routine;
                     87:        ipc_port_t *destp;
                     88: 
                     89:        reply = ikm_alloc(reply_size);
                     90:        if (reply == IKM_NULL) {
                     91:                printf("ipc_kobject_server: dropping request\n");
                     92:                ipc_kmsg_destroy(request);
                     93:                return IKM_NULL;
                     94:        }
                     95:        ikm_init(reply, reply_size);
                     96: 
                     97:        /*
                     98:         * Initialize reply message.
                     99:         */
                    100:        {
                    101: #define        InP     ((mach_msg_header_t *) &request->ikm_header)
                    102: #define        OutP    ((mig_reply_header_t *) &reply->ikm_header)
                    103: 
                    104:            static mach_msg_type_t RetCodeType = {
                    105:                /* msgt_name = */               MACH_MSG_TYPE_INTEGER_32,
                    106:                /* msgt_size = */               32,
                    107:                /* msgt_number = */             1,
                    108:                /* msgt_inline = */             TRUE,
                    109:                /* msgt_longform = */           FALSE,
                    110:                /* msgt_unused = */             0
                    111:            };
                    112:            OutP->Head.msgh_bits =
                    113:                MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
                    114:            OutP->Head.msgh_size = sizeof(mig_reply_header_t);
                    115:            OutP->Head.msgh_remote_port = InP->msgh_local_port;
                    116:            OutP->Head.msgh_local_port  = MACH_PORT_NULL;
                    117:            OutP->Head.msgh_seqno = 0;
                    118:            OutP->Head.msgh_id = InP->msgh_id + 100;
                    119: #if 0
                    120:            if (InP->msgh_id) {
                    121:                    static long _calls;
                    122:                    static struct { long id, count; } _counts[512];
                    123:                    int i, id;
                    124: 
                    125:                    id = InP->msgh_id;
                    126:                    for (i = 0; i < 511; i++) {
                    127:                            if (_counts[i].id == 0) {
                    128:                                    _counts[i].id = id;
                    129:                                    _counts[i].count++;
                    130:                                    break;
                    131:                            }
                    132:                            if (_counts[i].id == id) {
                    133:                                    _counts[i].count++;
                    134:                                    break;
                    135:                            }
                    136:                    }
                    137:                    if (i == 511) {
                    138:                            _counts[i].id = id;
                    139:                            _counts[i].count++;
                    140:                    }
                    141:                    if ((++_calls & 0x7fff) == 0)
                    142:                            for (i = 0; i < 512; i++) {
                    143:                                    if (_counts[i].id == 0)
                    144:                                            break;
                    145:                                    printf("%d: %d\n",
                    146:                                           _counts[i].id, _counts[i].count);
                    147:                            }
                    148:            }
                    149: #endif
                    150: 
                    151:            OutP->RetCodeType = RetCodeType;
                    152: 
                    153: #undef InP
                    154: #undef OutP
                    155:        }
                    156: 
                    157:        /*
                    158:         * Find the server routine to call, and call it
                    159:         * to perform the kernel function
                    160:         */
                    161:     {
                    162:        check_simple_locks();
                    163:        if ((routine = mach_server_routine(&request->ikm_header)) != 0
                    164:         || (routine = mach_port_server_routine(&request->ikm_header)) != 0
                    165:         || (routine = mach_host_server_routine(&request->ikm_header)) != 0
                    166:         || (routine = device_server_routine(&request->ikm_header)) != 0
                    167:         || (routine = device_pager_server_routine(&request->ikm_header)) != 0
                    168: #if    MACH_DEBUG
                    169:         || (routine = mach_debug_server_routine(&request->ikm_header)) != 0
1.1.1.2   root      170: #endif /* MACH_DEBUG */
1.1       root      171:         || (routine = mach4_server_routine(&request->ikm_header)) != 0
1.1.1.3   root      172:         || (routine = gnumach_server_routine(&request->ikm_header)) != 0
1.1       root      173: #if    MACH_MACHINE_ROUTINES
                    174:         || (routine = MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0
1.1.1.2   root      175: #endif /* MACH_MACHINE_ROUTINES */
1.1       root      176:        ) {
                    177:            (*routine)(&request->ikm_header, &reply->ikm_header);
1.1.1.3   root      178:            kernel_task->messages_received++;
                    179:        } else {
                    180:            if (!ipc_kobject_notify(&request->ikm_header,
                    181:                &reply->ikm_header)) {
1.1       root      182:                ((mig_reply_header_t *) &reply->ikm_header)->RetCode
                    183:                    = MIG_BAD_ID;
                    184: #if    MACH_IPC_TEST
                    185:                printf("ipc_kobject_server: bogus kernel message, id=%d\n",
                    186:                       request->ikm_header.msgh_id);
1.1.1.2   root      187: #endif /* MACH_IPC_TEST */
1.1.1.3   root      188:            } else {
                    189:                kernel_task->messages_received++;
                    190:            }
1.1       root      191:        }
1.1.1.3   root      192:        kernel_task->messages_sent++;
1.1       root      193:     }
                    194:        check_simple_locks();
                    195: 
                    196:        /*
                    197:         *      Destroy destination. The following code differs from
                    198:         *      ipc_object_destroy in that we release the send-once
                    199:         *      right instead of generating a send-once notification
                    200:         *      (which would bring us here again, creating a loop).
                    201:         *      It also differs in that we only expect send or
                    202:         *      send-once rights, never receive rights.
                    203:         *
                    204:         *      We set msgh_remote_port to IP_NULL so that the kmsg
                    205:         *      destroy routines don't try to destroy the port twice.
                    206:         */
                    207:        destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port;
                    208:        switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) {
                    209:                case MACH_MSG_TYPE_PORT_SEND:
                    210:                ipc_port_release_send(*destp);
                    211:                break;
1.1.1.2   root      212: 
1.1       root      213:                case MACH_MSG_TYPE_PORT_SEND_ONCE:
                    214:                ipc_port_release_sonce(*destp);
                    215:                break;
1.1.1.2   root      216: 
1.1       root      217:                default:
                    218: #if MACH_ASSERT
                    219:                assert(!"ipc_object_destroy: strange destination rights");
                    220: #else
                    221:                panic("ipc_object_destroy: strange destination rights");
                    222: #endif
                    223:        }
                    224:        *destp = IP_NULL;
                    225: 
                    226:        kr = ((mig_reply_header_t *) &reply->ikm_header)->RetCode;
                    227:        if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
                    228:                /*
                    229:                 *      The server function is responsible for the contents
                    230:                 *      of the message.  The reply port right is moved
                    231:                 *      to the reply message, and we have deallocated
                    232:                 *      the destination port right, so we just need
                    233:                 *      to free the kmsg.
                    234:                 */
                    235: 
                    236:                /* like ipc_kmsg_put, but without the copyout */
                    237: 
                    238:                ikm_check_initialized(request, request->ikm_size);
                    239:                if ((request->ikm_size == IKM_SAVED_KMSG_SIZE) &&
                    240:                    (ikm_cache() == IKM_NULL))
                    241:                        ikm_cache() = request;
                    242:                else
                    243:                        ikm_free(request);
                    244:        } else {
                    245:                /*
                    246:                 *      The message contents of the request are intact.
1.1.1.4 ! root      247:                 *      Destroy everything except the reply port right,
1.1       root      248:                 *      which is needed in the reply message.
                    249:                 */
                    250: 
                    251:                request->ikm_header.msgh_local_port = MACH_PORT_NULL;
                    252:                ipc_kmsg_destroy(request);
                    253:        }
                    254: 
                    255:        if (kr == MIG_NO_REPLY) {
                    256:                /*
                    257:                 *      The server function will send a reply message
                    258:                 *      using the reply port right, which it has saved.
                    259:                 */
                    260: 
                    261:                ikm_free(reply);
                    262:                return IKM_NULL;
                    263:        } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) {
                    264:                /*
                    265:                 *      Can't queue the reply message if the destination
                    266:                 *      (the reply port) isn't valid.
                    267:                 */
                    268: 
                    269:                ipc_kmsg_destroy(reply);
                    270:                return IKM_NULL;
                    271:        }
                    272: 
                    273:        return reply;
                    274: }
                    275: 
                    276: /*
                    277:  *     Routine:        ipc_kobject_set
                    278:  *     Purpose:
                    279:  *             Make a port represent a kernel object of the given type.
                    280:  *             The caller is responsible for handling refs for the
                    281:  *             kernel object, if necessary.
                    282:  *     Conditions:
                    283:  *             Nothing locked.  The port must be active.
                    284:  */
                    285: 
                    286: void
                    287: ipc_kobject_set(port, kobject, type)
                    288:        ipc_port_t port;
                    289:        ipc_kobject_t kobject;
                    290:        ipc_kobject_type_t type;
                    291: {
                    292:        ip_lock(port);
                    293:        assert(ip_active(port));
                    294:        port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type;
                    295:        port->ip_kobject = kobject;
                    296:        ip_unlock(port);
                    297: }
                    298: 
                    299: /*
                    300:  *     Routine:        ipc_kobject_destroy
                    301:  *     Purpose:
                    302:  *             Release any kernel object resources associated
                    303:  *             with the port, which is being destroyed.
                    304:  *
                    305:  *             This should only be needed when resources are
                    306:  *             associated with a user's port.  In the normal case,
                    307:  *             when the kernel is the receiver, the code calling
                    308:  *             ipc_port_dealloc_kernel should clean up the resources.
                    309:  *     Conditions:
                    310:  *             The port is not locked, but it is dead.
                    311:  */
                    312: 
                    313: void
                    314: ipc_kobject_destroy(
                    315:        ipc_port_t      port)
                    316: {
                    317:        switch (ip_kotype(port)) {
                    318:            case IKOT_PAGER:
                    319:                vm_object_destroy(port);
                    320:                break;
                    321: 
                    322:            case IKOT_PAGER_TERMINATING:
                    323:                vm_object_pager_wakeup(port);
                    324:                break;
                    325: 
                    326:            default:
                    327: #if    MACH_ASSERT
1.1.1.3   root      328:                printf("ipc_kobject_destroy: port 0x%p, kobj 0x%lx, type %d\n",
1.1       root      329:                       port, port->ip_kobject, ip_kotype(port));
1.1.1.2   root      330: #endif /* MACH_ASSERT */
1.1       root      331:                break;
                    332:        }
                    333: }
                    334: 
                    335: /*
                    336:  *     Routine:        ipc_kobject_notify
                    337:  *     Purpose:
                    338:  *             Deliver notifications to kobjects that care about them.
                    339:  */
                    340: 
                    341: boolean_t
                    342: ipc_kobject_notify(request_header, reply_header)
                    343:        mach_msg_header_t *request_header;
                    344:        mach_msg_header_t *reply_header;
                    345: {
                    346:        ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port;
                    347: 
                    348:        ((mig_reply_header_t *) reply_header)->RetCode = MIG_NO_REPLY;
                    349:        switch (request_header->msgh_id) {
                    350:                case MACH_NOTIFY_PORT_DELETED:
                    351:                case MACH_NOTIFY_MSG_ACCEPTED:
                    352:                case MACH_NOTIFY_PORT_DESTROYED:
                    353:                case MACH_NOTIFY_NO_SENDERS:
                    354:                case MACH_NOTIFY_SEND_ONCE:
                    355:                case MACH_NOTIFY_DEAD_NAME:
                    356:                break;
                    357: 
                    358:                default:
                    359:                return FALSE;
                    360:        }
                    361:        switch (ip_kotype(port)) {
                    362:                case IKOT_DEVICE:
                    363:                return ds_notify(request_header);
                    364: 
1.1.1.3   root      365:                case IKOT_PAGER_PROXY:
                    366:                return memory_object_proxy_notify(request_header);
                    367: 
1.1       root      368:                default:
                    369:                return FALSE;
                    370:        }
                    371: }

unix.superglobalmegacorp.com

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