Annotation of OSKit-Mach/kern/ipc_kobject.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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