Annotation of OSKit-Mach/kern/ipc_kobject.c, revision 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.