123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- /*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
- /*
- */
- /*
- * File: kern/ipc_kobject.c
- * Author: Rich Draves
- * Date: 1989
- *
- * Functions for letting a port represent a kernel object.
- */
- #include <glue/gnulinux.h>
- #include <kern/debug.h>
- #include <kern/printf.h>
- #include <mach/port.h>
- #include <mach/kern_return.h>
- #include <mach/message.h>
- //#include <mach/mig_errors.h>
- #include <mach/notify.h>
- #include <kern/ipc_kobject.h>
- #include <ipc/ipc_object.h>
- #include <ipc/ipc_kmsg.h>
- #include <ipc/ipc_port.h>
- #include <ipc/ipc_thread.h>
- #include <vm/vm_object.h>
- #include <vm/memory_object_proxy.h>
- #if 0
- #include <device/ds_routines.h>
- #include <kern/mach.server.h>
- #include <ipc/mach_port.server.h>
- #include <kern/mach_host.server.h>
- #include <device/device.server.h>
- #include <device/device_pager.server.h>
- #include <kern/mach4.server.h>
- #include <kern/gnumach.server.h>
- #if MACH_DEBUG
- #include <kern/mach_debug.server.h>
- #endif
- #if MACH_MACHINE_ROUTINES
- #include <machine/machine_routines.h>
- #include MACHINE_SERVER_HEADER
- #endif
- /*
- * Routine: ipc_kobject_server
- * Purpose:
- * Handle a message sent to the kernel.
- * Generates a reply message.
- * Conditions:
- * Nothing locked.
- */
- ipc_kmsg_t
- ipc_kobject_server(request)
- ipc_kmsg_t request;
- {
- mach_msg_size_t reply_size = ikm_less_overhead(8192);
- ipc_kmsg_t reply;
- kern_return_t kr;
- mig_routine_t routine;
- ipc_port_t *destp;
- reply = ikm_alloc(reply_size);
- if (reply == IKM_NULL) {
- printf("ipc_kobject_server: dropping request\n");
- ipc_kmsg_destroy(request);
- return IKM_NULL;
- }
- ikm_init(reply, reply_size);
- /*
- * Initialize reply message.
- */
- {
- #define InP ((mach_msg_header_t *) &request->ikm_header)
- #define OutP ((mig_reply_header_t *) &reply->ikm_header)
- static mach_msg_type_t RetCodeType = {
- /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32,
- /* msgt_size = */ 32,
- /* msgt_number = */ 1,
- /* msgt_inline = */ TRUE,
- /* msgt_longform = */ FALSE,
- /* msgt_unused = */ 0
- };
- OutP->Head.msgh_bits =
- MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
- OutP->Head.msgh_size = sizeof(mig_reply_header_t);
- OutP->Head.msgh_remote_port = InP->msgh_local_port;
- OutP->Head.msgh_local_port = MACH_PORT_NULL;
- OutP->Head.msgh_seqno = 0;
- OutP->Head.msgh_id = InP->msgh_id + 100;
- #if 0
- if (InP->msgh_id) {
- static long _calls;
- static struct { long id, count; } _counts[512];
- int i, id;
- id = InP->msgh_id;
- for (i = 0; i < 511; i++) {
- if (_counts[i].id == 0) {
- _counts[i].id = id;
- _counts[i].count++;
- break;
- }
- if (_counts[i].id == id) {
- _counts[i].count++;
- break;
- }
- }
- if (i == 511) {
- _counts[i].id = id;
- _counts[i].count++;
- }
- if ((++_calls & 0x7fff) == 0)
- for (i = 0; i < 512; i++) {
- if (_counts[i].id == 0)
- break;
- printf("%d: %d\n",
- _counts[i].id, _counts[i].count);
- }
- }
- #endif
- OutP->RetCodeType = RetCodeType;
- #undef InP
- #undef OutP
- }
- /*
- * Find the server routine to call, and call it
- * to perform the kernel function
- */
- {
- check_simple_locks();
- if ((routine = mach_server_routine(&request->ikm_header)) != 0
- || (routine = mach_port_server_routine(&request->ikm_header)) != 0
- || (routine = mach_host_server_routine(&request->ikm_header)) != 0
- || (routine = device_server_routine(&request->ikm_header)) != 0
- || (routine = device_pager_server_routine(&request->ikm_header)) != 0
- #if MACH_DEBUG
- || (routine = mach_debug_server_routine(&request->ikm_header)) != 0
- #endif /* MACH_DEBUG */
- || (routine = mach4_server_routine(&request->ikm_header)) != 0
- || (routine = gnumach_server_routine(&request->ikm_header)) != 0
- #if MACH_MACHINE_ROUTINES
- || (routine = MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0
- #endif /* MACH_MACHINE_ROUTINES */
- ) {
- (*routine)(&request->ikm_header, &reply->ikm_header);
- kernel_task->messages_received++;
- } else {
- if (!ipc_kobject_notify(&request->ikm_header,
- &reply->ikm_header)) {
- ((mig_reply_header_t *) &reply->ikm_header)->RetCode
- = MIG_BAD_ID;
- #if MACH_IPC_TEST
- printf("ipc_kobject_server: bogus kernel message, id=%d\n",
- request->ikm_header.msgh_id);
- #endif /* MACH_IPC_TEST */
- } else {
- kernel_task->messages_received++;
- }
- }
- kernel_task->messages_sent++;
- }
- check_simple_locks();
- /*
- * Destroy destination. The following code differs from
- * ipc_object_destroy in that we release the send-once
- * right instead of generating a send-once notification
- * (which would bring us here again, creating a loop).
- * It also differs in that we only expect send or
- * send-once rights, never receive rights.
- *
- * We set msgh_remote_port to IP_NULL so that the kmsg
- * destroy routines don't try to destroy the port twice.
- */
- destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port;
- switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) {
- case MACH_MSG_TYPE_PORT_SEND:
- ipc_port_release_send(*destp);
- break;
- case MACH_MSG_TYPE_PORT_SEND_ONCE:
- ipc_port_release_sonce(*destp);
- break;
- default:
- #if MACH_ASSERT
- assert(!"ipc_object_destroy: strange destination rights");
- #else
- panic("ipc_object_destroy: strange destination rights");
- #endif
- }
- *destp = IP_NULL;
- kr = ((mig_reply_header_t *) &reply->ikm_header)->RetCode;
- if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
- /*
- * The server function is responsible for the contents
- * of the message. The reply port right is moved
- * to the reply message, and we have deallocated
- * the destination port right, so we just need
- * to free the kmsg.
- */
- /* like ipc_kmsg_put, but without the copyout */
- ikm_check_initialized(request, request->ikm_size);
- if ((request->ikm_size == IKM_SAVED_KMSG_SIZE) &&
- (ikm_cache() == IKM_NULL))
- ikm_cache() = request;
- else
- ikm_free(request);
- } else {
- /*
- * The message contents of the request are intact.
- * Destroy everything except the reply port right,
- * which is needed in the reply message.
- */
- request->ikm_header.msgh_local_port = MACH_PORT_NULL;
- ipc_kmsg_destroy(request);
- }
- if (kr == MIG_NO_REPLY) {
- /*
- * The server function will send a reply message
- * using the reply port right, which it has saved.
- */
- ikm_free(reply);
- return IKM_NULL;
- } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) {
- /*
- * Can't queue the reply message if the destination
- * (the reply port) isn't valid.
- */
- ipc_kmsg_destroy(reply);
- return IKM_NULL;
- }
- return reply;
- }
- #endif
- /*
- * Routine: ipc_kobject_set
- * Purpose:
- * Make a port represent a kernel object of the given type.
- * The caller is responsible for handling refs for the
- * kernel object, if necessary.
- * Conditions:
- * Nothing locked. The port must be active.
- */
- void
- ipc_kobject_set(port, kobject, type)
- ipc_port_t port;
- ipc_kobject_t kobject;
- ipc_kobject_type_t type;
- {
- ip_lock(port);
- assert(ip_active(port));
- port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type;
- port->ip_kobject = kobject;
- ip_unlock(port);
- }
- #if 0
- /*
- * Routine: ipc_kobject_destroy
- * Purpose:
- * Release any kernel object resources associated
- * with the port, which is being destroyed.
- *
- * This should only be needed when resources are
- * associated with a user's port. In the normal case,
- * when the kernel is the receiver, the code calling
- * ipc_port_dealloc_kernel should clean up the resources.
- * Conditions:
- * The port is not locked, but it is dead.
- */
- void
- ipc_kobject_destroy(
- ipc_port_t port)
- {
- switch (ip_kotype(port)) {
- case IKOT_PAGER:
- vm_object_destroy(port);
- break;
- case IKOT_PAGER_TERMINATING:
- vm_object_pager_wakeup(port);
- break;
- default:
- #if MACH_ASSERT
- printf("ipc_kobject_destroy: port 0x%p, kobj 0x%lx, type %d\n",
- port, port->ip_kobject, ip_kotype(port));
- #endif /* MACH_ASSERT */
- break;
- }
- }
- /*
- * Routine: ipc_kobject_notify
- * Purpose:
- * Deliver notifications to kobjects that care about them.
- */
- boolean_t
- ipc_kobject_notify(request_header, reply_header)
- mach_msg_header_t *request_header;
- mach_msg_header_t *reply_header;
- {
- ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port;
- ((mig_reply_header_t *) reply_header)->RetCode = MIG_NO_REPLY;
- switch (request_header->msgh_id) {
- case MACH_NOTIFY_PORT_DELETED:
- case MACH_NOTIFY_MSG_ACCEPTED:
- case MACH_NOTIFY_PORT_DESTROYED:
- case MACH_NOTIFY_NO_SENDERS:
- case MACH_NOTIFY_SEND_ONCE:
- case MACH_NOTIFY_DEAD_NAME:
- break;
- default:
- return FALSE;
- }
- switch (ip_kotype(port)) {
- case IKOT_DEVICE:
- return ds_notify(request_header);
- case IKOT_PAGER_PROXY:
- return memory_object_proxy_notify(request_header);
- default:
- return FALSE;
- }
- }
- #endif
|