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

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

unix.superglobalmegacorp.com

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