|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50: /*
51: */
52: /*
53: * File: kern/ipc_kobject.c
54: * Author: Rich Draves
55: * Date: 1989
56: *
57: * Functions for letting a port represent a kernel object.
58: */
59:
60: #include <mach_debug.h>
61: #include <mach_ipc_test.h>
62: #include <mach_machine_routines.h>
63: #include <norma_task.h>
64: #include <dipc.h>
65: #include <mach_rt.h>
66: #include <platforms.h>
67: #include <xk_proxy.h>
68:
69: #include <kern/ast.h>
70: #include <mach/port.h>
71: #include <mach/kern_return.h>
72: #include <mach/message.h>
73: #include <mach/mig_errors.h>
74: #include <mach/notify.h>
75: #include <kern/etap_macros.h>
76: #include <kern/ipc_mig.h>
77: #include <kern/ipc_kobject.h>
78: #include <kern/misc_protos.h>
79: #include <ipc/ipc_object.h>
80: #include <ipc/ipc_kmsg.h>
81: #include <ipc/ipc_port.h>
82: #include <kern/counters.h>
83:
84:
85: void
86: def_pager_hash_insert(
87: ipc_port_t name_port);
88: void pager_mux_hash_insert(
89: ipc_port_t port,
90: rpc_subsystem_t rec);
91: void pager_mux_hash_delete(
92: ipc_port_t port);
93: rpc_subsystem_t pager_mux_hash_lookup(
94: ipc_port_t port);
95:
96:
97: /*
98: * Routine: ipc_kobject_notify
99: * Purpose:
100: * Deliver notifications to kobjects that care about them.
101: */
102: boolean_t
103: ipc_kobject_notify(
104: mach_msg_header_t *request_header,
105: mach_msg_header_t *reply_header);
106:
107: #include <mach/ndr.h>
108:
109: typedef struct {
110: mach_msg_id_t num;
111: mig_routine_t routine;
112: int size;
113: #if MACH_COUNTERS
114: mach_counter_t callcount;
115: #endif
116: } mig_hash_t;
117:
118: #define MAX_MIG_ENTRIES 1024
119: #define MIG_HASH(x) (x)
120:
121: #ifndef max
122: #define max(a,b) (((a) > (b)) ? (a) : (b))
123: #endif /* max */
124:
125: mig_hash_t mig_buckets[MAX_MIG_ENTRIES];
126: int mig_table_max_displ;
127: mach_msg_size_t mig_reply_size;
128:
129:
130: #include <mach/mach_port_server.h>
131: #include <mach/mach_host_server.h>
132: #include <mach/host_priv_server.h>
133: #include <mach/host_security_server.h>
134: #include <mach/clock_server.h>
135: #include <mach/clock_priv_server.h>
136: #include <mach/bootstrap_server.h>
137: #include <mach/ledger_server.h>
138: #include <mach/lock_set_server.h>
139: #include <mach/semaphore_server.h>
140: #include <default_pager/default_pager_object_server.h>
141: #include <mach/memory_object_server.h>
142: #include <mach/memory_object_control_server.h>
143: #include <mach/memory_object_default_server.h>
144: #include <mach/memory_object_name_server.h>
145: #include <mach/processor_server.h>
146: #include <mach/processor_set_server.h>
147: #include <mach/task_server.h>
148: #include <mach/vm_task_server.h>
149: #include <mach/thread_act_server.h>
150: #include <device/device_server.h>
151:
152: #if MACH_MACHINE_ROUTINES
153: #include <machine/machine_routines.h>
154: #endif /* MACH_MACHINE_ROUTINES */
155: #if XK_PROXY
156: #include <uk_xkern/xk_uproxy_server.h>
157: #endif /* XK_PROXY */
158:
159:
160: rpc_subsystem_t mig_e[] = {
161: (rpc_subsystem_t)&mach_port_subsystem,
162: (rpc_subsystem_t)&mach_host_subsystem,
163: (rpc_subsystem_t)&host_priv_subsystem,
164: (rpc_subsystem_t)&host_security_subsystem,
165: (rpc_subsystem_t)&clock_subsystem,
166: (rpc_subsystem_t)&clock_priv_subsystem,
167: (rpc_subsystem_t)&processor_subsystem,
168: (rpc_subsystem_t)&processor_set_subsystem,
169: (rpc_subsystem_t)&do_bootstrap_subsystem,
170: (rpc_subsystem_t)&is_iokit_subsystem,
171: (rpc_subsystem_t)&dp_memory_object_subsystem,
172: (rpc_subsystem_t)&dp_memory_object_default_subsystem,
173: (rpc_subsystem_t)&memory_object_name_subsystem,
174: (rpc_subsystem_t)&default_pager_object_subsystem,
175: (rpc_subsystem_t)&semaphore_subsystem,
176: (rpc_subsystem_t)&lock_set_subsystem,
177: (rpc_subsystem_t)&ledger_subsystem,
178: (rpc_subsystem_t)&task_subsystem,
179: (rpc_subsystem_t)&thread_act_subsystem,
180: (rpc_subsystem_t)&vm_task_subsystem,
181:
182: #if XK_PROXY
183: (rpc_subsystem_t)&do_uproxy_xk_uproxy_subsystem,
184: #endif /* XK_PROXY */
185: #if MACH_MACHINE_ROUTINES
186: (rpc_subsystem_t)&MACHINE_SUBSYSTEM,
187: #endif /* MACH_MACHINE_ROUTINES */
188: #if MCMSG && iPSC860
189: (rpc_subsystem_t)&mcmsg_info_subsystem,
190: #endif /* MCMSG && iPSC860 */
191: };
192:
193: void
194: mig_init(void)
195: {
196: register unsigned int i, n = sizeof(mig_e)/sizeof(rpc_subsystem_t);
197: register unsigned int howmany;
198: register mach_msg_id_t j, pos, nentry, range;
199:
200: for (i = 0; i < n; i++) {
201: range = mig_e[i]->end - mig_e[i]->start;
202: if (!mig_e[i]->start || range < 0)
203: panic("the msgh_ids in mig_e[] aren't valid!");
204: mig_reply_size = max(mig_reply_size, mig_e[i]->maxsize);
205:
206: for (j = 0; j < range; j++) {
207: if (mig_e[i]->routine[j].stub_routine) {
208: /* Only put real entries in the table */
209: nentry = j + mig_e[i]->start;
210: for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1;
211: mig_buckets[pos].num;
212: pos = ++pos % MAX_MIG_ENTRIES, howmany++) {
213: if (mig_buckets[pos].num == nentry) {
214: printf("message id = %d\n", nentry);
215: panic("multiple entries with the same msgh_id");
216: }
217: if (howmany == MAX_MIG_ENTRIES)
218: panic("the mig dispatch table is too small");
219: }
220:
221: mig_buckets[pos].num = nentry;
222: mig_buckets[pos].routine = mig_e[i]->routine[j].stub_routine;
223: if (mig_e[i]->routine[j].max_reply_msg)
224: mig_buckets[pos].size = mig_e[i]->routine[j].max_reply_msg;
225: else
226: mig_buckets[pos].size = mig_e[i]->maxsize;
227:
228: mig_table_max_displ = max(howmany, mig_table_max_displ);
229: }
230: }
231: }
232: }
233:
234:
235: #define PAGER_MUX_HASH_COUNT 127
236:
237:
238: struct pager_mux_entry {
239: queue_chain_t links;
240: ipc_port_t name;
241: rpc_subsystem_t pager_object;
242: };
243: typedef struct pager_mux_entry *pager_mux_entry_t;
244:
245: queue_head_t pager_mux_hashtable[PAGER_MUX_HASH_COUNT];
246: zone_t pager_mux_hash_zone;
247:
248: decl_mutex_data(,pager_mux_hash_lock)
249:
250: #define pager_mux_hash(name_port) \
251: (((natural_t)(name_port) & 0xffffff) % PAGER_MUX_HASH_COUNT)
252:
253:
254: rpc_subsystem_t
255: pager_mux_hash_lookup(
256: ipc_port_t name_port)
257: {
258: register queue_t bucket;
259: register pager_mux_entry_t entry;
260: register rpc_subsystem_t pager_object;
261:
262: bucket = &pager_mux_hashtable[pager_mux_hash(name_port)];
263:
264: mutex_lock(&pager_mux_hash_lock);
265: for (entry = (pager_mux_entry_t)queue_first(bucket);
266: !queue_end(bucket, &entry->links);
267: entry = (pager_mux_entry_t)queue_next(&entry->links)) {
268: if (entry->name == name_port) {
269: pager_object = entry->pager_object;
270: /* don't need to reference the object, it can't disappear */
271: /* pager_mux_reference(pager_object); */
272: mutex_unlock(&pager_mux_hash_lock);
273: return (pager_object);
274: }
275: }
276: mutex_unlock(&pager_mux_hash_lock);
277: return (rpc_subsystem_t)0;
278: }
279:
280:
281: void
282: pager_mux_hash_init(void)
283: {
284: register int i;
285: register vm_size_t size;
286:
287: size = sizeof(struct pager_mux_entry);
288: pager_mux_hash_zone = zinit(
289: size,
290: size * 2000,
291: PAGE_SIZE,
292: "pager mux port hash");
293: for (i = 0; i < PAGER_MUX_HASH_COUNT; i++)
294: queue_init(&pager_mux_hashtable[i]);
295: mutex_init(&pager_mux_hash_lock, ETAP_IO_DEV_PAGEH);
296: }
297:
298:
299: void
300: pager_mux_hash_insert(
301: ipc_port_t name_port,
302: rpc_subsystem_t pager_object)
303: {
304: register pager_mux_entry_t new_entry;
305:
306: new_entry = (pager_mux_entry_t) zalloc(pager_mux_hash_zone);
307: new_entry->links.prev = (queue_entry_t) 0;
308: new_entry->links.next = (queue_entry_t) 0;
309: new_entry->name = name_port;
310: new_entry->pager_object = pager_object;
311:
312: mutex_lock(&pager_mux_hash_lock);
313: queue_enter((&pager_mux_hashtable[pager_mux_hash(name_port)]),
314: new_entry, pager_mux_entry_t, links);
315: mutex_unlock(&pager_mux_hash_lock);
316: }
317:
318: void
319: pager_mux_hash_delete(
320: ipc_port_t name_port)
321: {
322: register queue_t bucket;
323: register pager_mux_entry_t entry;
324:
325: bucket = &pager_mux_hashtable[pager_mux_hash(name_port)];
326:
327: mutex_lock(&pager_mux_hash_lock);
328: for (entry = (pager_mux_entry_t)queue_first(bucket);
329: !queue_end(bucket, &entry->links);
330: entry = (pager_mux_entry_t)queue_next(&entry->links)) {
331: if (entry->name == name_port) {
332: queue_remove(bucket, entry, pager_mux_entry_t, links);
333: zfree(pager_mux_hash_zone, (vm_offset_t)entry);
334: break;
335: }
336: }
337: mutex_unlock(&pager_mux_hash_lock);
338: }
339:
340:
341: /*
342: * Routine: ipc_kobject_server
343: * Purpose:
344: * Handle a message sent to the kernel.
345: * Generates a reply message.
346: * Version for Untyped IPC.
347: * Conditions:
348: * Nothing locked.
349: */
350:
351: ipc_kmsg_t
352: ipc_kobject_server(
353: ipc_kmsg_t request)
354: {
355: mach_msg_size_t reply_size;
356: ipc_kmsg_t reply;
357: kern_return_t kr;
358: mig_routine_t routine;
359: ipc_port_t *destp;
360: mach_msg_format_0_trailer_t *trailer;
361: register mig_hash_t *ptr;
362: #if MACH_RT
363: boolean_t reply_rt;
364: #endif /* MACH_RT */
365: unsigned int th;
366:
367: /* Only fetch current thread if ETAP is configured */
368: ETAP_DATA_LOAD(th, current_thread());
369: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH,
370: EVENT_BEGIN,
371: ((thread_t) th),
372: &request->ikm_header.msgh_id,
373: sizeof(int));
374: /*
375: * Find out corresponding mig_hash entry if any
376: */
377: {
378: register int key = request->ikm_header.msgh_id;
379: register int i = MIG_HASH(key);
380: register int max_iter = mig_table_max_displ;
381:
382: do
383: ptr = &mig_buckets[i++ % MAX_MIG_ENTRIES];
384: while (key != ptr->num && ptr->num && --max_iter);
385:
386: if (!ptr->routine || key != ptr->num) {
387: ptr = (mig_hash_t *)0;
388: reply_size = mig_reply_size;
389: } else {
390: reply_size = ptr->size;
391: #if MACH_COUNTER
392: ptr->callcount++;
393: #endif
394: }
395: }
396:
397: /* round up for ikm_cache; overhead is added by ikm_alloc */
398: if ((reply_size += MAX_TRAILER_SIZE) < IKM_SAVED_MSG_SIZE)
399: reply_size = IKM_SAVED_MSG_SIZE;
400:
401: #if MACH_RT
402: reply_rt =
403: IP_VALID((ipc_port_t)request->ikm_header.msgh_local_port) ?
404: IP_RT((ipc_port_t)request->ikm_header.msgh_local_port) :
405: FALSE;
406:
407: if (reply_rt)
408: reply = ikm_rtalloc(reply_size);
409: else
410: #endif /* MACH_RT */
411: reply = ikm_alloc(reply_size);
412:
413: if (reply == IKM_NULL) {
414: printf("ipc_kobject_server: dropping request\n");
415: ipc_kmsg_destroy(request);
416: return IKM_NULL;
417: }
418:
419: ikm_init(reply, reply_size);
420: #if DIPC
421: reply->ikm_handle = HANDLE_NULL;
422: #endif /* DIPC */
423:
424: /*
425: * Initialize reply message.
426: */
427: {
428: #define InP ((mach_msg_header_t *) &request->ikm_header)
429: #define OutP ((mig_reply_error_t *) &reply->ikm_header)
430:
431: OutP->NDR = NDR_record;
432: OutP->Head.msgh_size = sizeof(mig_reply_error_t);
433:
434: OutP->Head.msgh_bits =
435: MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
436: OutP->Head.msgh_remote_port = InP->msgh_local_port;
437: OutP->Head.msgh_local_port = MACH_PORT_NULL;
438: OutP->Head.msgh_id = InP->msgh_id + 100;
439: #if MACH_RT
440: if (reply_rt)
441: KMSG_MARK_RT(reply);
442: #endif /* MACH_RT */
443: #undef InP
444: #undef OutP
445: }
446:
447: /*
448: * Find the routine to call, and call it
449: * to perform the kernel function
450: */
451: {
452: if (ptr) {
453: (*ptr->routine)(&request->ikm_header, &reply->ikm_header);
454: kernel_task->messages_received++;
455: }
456: else {
457: if (!ipc_kobject_notify(&request->ikm_header, &reply->ikm_header)){
458: #if MACH_IPC_TEST
459: printf("ipc_kobject_server: bogus kernel message, id=%d\n",
460: request->ikm_header.msgh_id);
461: #endif /* MACH_IPC_TEST */
462: _MIG_MSGID_INVALID(request->ikm_header.msgh_id);
463:
464: ((mig_reply_error_t *) &reply->ikm_header)->RetCode
465: = MIG_BAD_ID;
466: }
467: else
468: kernel_task->messages_received++;
469: }
470: kernel_task->messages_sent++;
471: }
472:
473: /*
474: * Destroy destination. The following code differs from
475: * ipc_object_destroy in that we release the send-once
476: * right instead of generating a send-once notification
477: * (which would bring us here again, creating a loop).
478: * It also differs in that we only expect send or
479: * send-once rights, never receive rights.
480: *
481: * We set msgh_remote_port to IP_NULL so that the kmsg
482: * destroy routines don't try to destroy the port twice.
483: */
484: destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port;
485: switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) {
486: case MACH_MSG_TYPE_PORT_SEND:
487: ipc_port_release_send(*destp);
488: break;
489:
490: case MACH_MSG_TYPE_PORT_SEND_ONCE:
491: ipc_port_release_sonce(*destp);
492: break;
493:
494: default:
495: panic("ipc_object_destroy: strange destination rights");
496: }
497: *destp = IP_NULL;
498:
499: if (!(reply->ikm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
500: ((mig_reply_error_t *) &reply->ikm_header)->RetCode != KERN_SUCCESS)
501: kr = ((mig_reply_error_t *) &reply->ikm_header)->RetCode;
502: else
503: kr = KERN_SUCCESS;
504:
505: if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
506: /*
507: * The server function is responsible for the contents
508: * of the message. The reply port right is moved
509: * to the reply message, and we have deallocated
510: * the destination port right, so we just need
511: * to free the kmsg.
512: */
513:
514: /*
515: * Like ipc_kmsg_put, but without the copyout. Also,
516: * messages to the kernel will never have been allocated
517: * from the rt_zone.
518: */
519:
520: ikm_check_initialized(request, request->ikm_size);
521: if (request->ikm_size != IKM_SAVED_KMSG_SIZE ||
522: !ikm_cache_put (request)) {
523: ikm_free(request);
524: }
525: } else {
526: /*
527: * The message contents of the request are intact.
528: * Destroy everthing except the reply port right,
529: * which is needed in the reply message.
530: */
531:
532: request->ikm_header.msgh_local_port = MACH_PORT_NULL;
533: ipc_kmsg_destroy(request);
534: }
535:
536: if (kr == MIG_NO_REPLY) {
537: /*
538: * The server function will send a reply message
539: * using the reply port right, which it has saved.
540: */
541:
542: ikm_free(reply);
543:
544: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH,
545: EVENT_END,
546: ((thread_t) th),
547: &request->ikm_header.msgh_id,
548: sizeof(int));
549:
550: return IKM_NULL;
551: } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) {
552: /*
553: * Can't queue the reply message if the destination
554: * (the reply port) isn't valid.
555: */
556:
557: ipc_kmsg_destroy(reply);
558:
559: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH,
560: EVENT_END,
561: ((thread_t) th),
562: &request->ikm_header.msgh_id,
563: sizeof(int));
564:
565: return IKM_NULL;
566: }
567:
568: trailer = (mach_msg_format_0_trailer_t *)
569: ((vm_offset_t)&reply->ikm_header + (int)reply->ikm_header.msgh_size);
570: trailer->msgh_sender = KERNEL_SECURITY_TOKEN;
571: trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
572: trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
573:
574: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH,
575: EVENT_END,
576: ((thread_t) th),
577: &request->ikm_header.msgh_id,
578: sizeof(int));
579:
580: return reply;
581: }
582:
583: /*
584: * Routine: ipc_kobject_set
585: * Purpose:
586: * Make a port represent a kernel object of the given type.
587: * The caller is responsible for handling refs for the
588: * kernel object, if necessary.
589: * Conditions:
590: * Nothing locked. The port must be active.
591: */
592:
593: void
594: ipc_kobject_set(
595: ipc_port_t port,
596: ipc_kobject_t kobject,
597: ipc_kobject_type_t type)
598: {
599: ip_lock(port);
600: assert(ip_active(port));
601: #if MACH_ASSERT
602: port->ip_spares[2] = (port->ip_bits & IO_BITS_KOTYPE);
603: #endif /* MACH_ASSERT */
604: port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type;
605: port->ip_kobject = kobject;
606: ip_unlock(port);
607: }
608:
609: /*
610: * Routine: ipc_kobject_destroy
611: * Purpose:
612: * Release any kernel object resources associated
613: * with the port, which is being destroyed.
614: *
615: * This should only be needed when resources are
616: * associated with a user's port. In the normal case,
617: * when the kernel is the receiver, the code calling
618: * ipc_port_dealloc_kernel should clean up the resources.
619: * Conditions:
620: * The port is not locked, but it is dead.
621: */
622:
623: void
624: ipc_kobject_destroy(
625: ipc_port_t port)
626: {
627: switch (ip_kotype(port)) {
628: case IKOT_NAMED_ENTRY:
629: mach_destroy_memory_entry(port);
630: return;
631: case IKOT_UPL:
632: mach_destroy_upl(port);
633: return;
634: default:
635: vm_object_destroy(port);
636: }
637: }
638:
639:
640: extern int vnode_pager_workaround;
641:
642: boolean_t
643: ipc_kobject_notify(
644: mach_msg_header_t *request_header,
645: mach_msg_header_t *reply_header)
646: {
647: ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port;
648: rpc_subsystem_t paging_subsystem_object;
649: mach_port_seqno_t seqno;
650:
651: ((mig_reply_error_t *) reply_header)->RetCode = MIG_NO_REPLY;
652: switch (request_header->msgh_id) {
653: case MACH_NOTIFY_NO_SENDERS:
654: if(ip_kotype(port) == IKOT_NAMED_ENTRY) {
655: ip_lock(port);
656:
657: /*
658: * Bring the sequence number and mscount in
659: * line with ipc_port_destroy assertion.
660: */
661: port->ip_mscount = 0;
662: port->ip_messages.imq_seqno = 0;
663: ipc_port_destroy(port); /* releases lock */
664: return TRUE;
665: }
666: paging_subsystem_object = pager_mux_hash_lookup(
667: (ipc_port_t)request_header->msgh_remote_port);
668: if(paging_subsystem_object == (rpc_subsystem_t)
669: &dp_memory_object_subsystem) {
670: default_pager_no_senders(
671: (ipc_port_t)request_header->msgh_remote_port,
672: seqno,
673: (mach_port_mscount_t)
674: ((mach_no_senders_notification_t *)
675: request_header)->not_count);
676: (ipc_port_t)reply_header->msgh_remote_port
677: = MACH_PORT_NULL;
678: return TRUE;
679: }
680: if(paging_subsystem_object == (rpc_subsystem_t)
681: &vnode_pager_workaround) {
682: vnode_pager_no_senders(
683: (ipc_port_t)request_header->msgh_remote_port,
684: (mach_port_mscount_t)
685: ((mach_no_senders_notification_t *)
686: request_header)->not_count);
687: (ipc_port_t)reply_header->msgh_remote_port
688: = MACH_PORT_NULL;
689: return TRUE;
690: }
691: break;
692: case MACH_NOTIFY_PORT_DELETED:
693: case MACH_NOTIFY_PORT_DESTROYED:
694: case MACH_NOTIFY_SEND_ONCE:
695: case MACH_NOTIFY_DEAD_NAME:
696: break;
697:
698: default:
699: return FALSE;
700: }
701: switch (ip_kotype(port)) {
702:
703: #ifdef IOKIT
704: case IKOT_IOKIT_OBJECT:
705: case IKOT_IOKIT_CONNECT:
706: case IKOT_IOKIT_SPARE:
707: {
708: extern boolean_t iokit_notify( mach_msg_header_t *msg);
709:
710: return iokit_notify(request_header);
711: }
712: #endif
713: default:
714: return FALSE;
715: }
716: }
717:
718:
719:
720: #include <mach_kdb.h>
721: #if MACH_COUNTERS && MACH_KDB
722:
723: #include <ddb/db_output.h>
724: #include <ddb/db_sym.h>
725:
726: #define printf kdbprintf
727:
728: extern void kobjserver_stats(void);
729: extern void bucket_stats_print(mig_hash_t *bucket);
730:
731: extern void kobjserver_stats_clear(void);
732:
733:
734: void
735: kobjserver_stats_clear(void)
736: {
737: int i;
738: for (i = 0; i < MAX_MIG_ENTRIES; i++) {
739: mig_buckets[i].callcount = 0;
740: }
741: }
742:
743: void
744: kobjserver_stats(void)
745: {
746: register unsigned int i, n = sizeof(mig_e)/sizeof(rpc_subsystem_t);
747: register unsigned int howmany;
748: register mach_msg_id_t j, pos, nentry, range;
749:
750: db_printf("Kobject server call counts:\n");
751: for (i = 0; i < n; i++) {
752: db_printf(" ");
753: db_printsym((vm_offset_t)mig_e[i], DB_STGY_ANY);
754: db_printf(":\n");
755: range = mig_e[i]->end - mig_e[i]->start;
756: if (!mig_e[i]->start || range < 0) continue;
757:
758: for (j = 0; j < range; j++) {
759: nentry = j + mig_e[i]->start;
760: for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1;
761: mig_buckets[pos].num;
762: pos = ++pos % MAX_MIG_ENTRIES, howmany++) {
763: if (mig_buckets[pos].num == nentry)
764: bucket_stats_print(&mig_buckets[pos]);
765: }
766: }
767: }
768: }
769:
770: void
771: bucket_stats_print(mig_hash_t *bucket)
772: {
773: if (bucket->callcount) {
774: db_printf(" ");
775: db_printsym((vm_offset_t)bucket->routine, DB_STGY_ANY);
776: db_printf(" (%d):\t%d\n", bucket->num, bucket->callcount);
777: }
778: }
779:
780:
781: #endif /* MACH_COUNTERS && MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.