|
|
1.1.1.2 root 1: /*
1.1 root 2: * Mach Operating System
3: * Copyright (c) 1991,1990 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: ipc/mach_debug.c
30: * Author: Rich Draves
31: * Date: 1989
32: *
33: * Exported kernel calls. See mach_debug/mach_debug.defs.
34: */
35:
1.1.1.3 root 36: #include <string.h>
1.1 root 37:
38: #include <mach/kern_return.h>
39: #include <mach/port.h>
40: #include <mach/machine/vm_types.h>
41: #include <mach/vm_param.h>
42: #include <mach_debug/ipc_info.h>
43: #include <mach_debug/hash_info.h>
44: #include <kern/host.h>
45: #include <vm/vm_map.h>
46: #include <vm/vm_kern.h>
47: #include <ipc/ipc_space.h>
48: #include <ipc/ipc_port.h>
49: #include <ipc/ipc_hash.h>
50: #include <ipc/ipc_marequest.h>
51: #include <ipc/ipc_table.h>
52: #include <ipc/ipc_right.h>
53:
54:
55:
56: /*
57: * Routine: mach_port_get_srights [kernel call]
58: * Purpose:
59: * Retrieve the number of extant send rights
60: * that a receive right has.
61: * Conditions:
62: * Nothing locked.
63: * Returns:
64: * KERN_SUCCESS Retrieved number of send rights.
65: * KERN_INVALID_TASK The space is null.
66: * KERN_INVALID_TASK The space is dead.
67: * KERN_INVALID_NAME The name doesn't denote a right.
68: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
69: */
70:
71: kern_return_t
72: mach_port_get_srights(
73: ipc_space_t space,
74: mach_port_t name,
75: mach_port_rights_t *srightsp)
76: {
77: ipc_port_t port;
78: kern_return_t kr;
79: mach_port_rights_t srights;
80:
81: if (space == IS_NULL)
82: return KERN_INVALID_TASK;
83:
84: kr = ipc_port_translate_receive(space, name, &port);
85: if (kr != KERN_SUCCESS)
86: return kr;
87: /* port is locked and active */
88:
89: srights = port->ip_srights;
90: ip_unlock(port);
91:
92: *srightsp = srights;
93: return KERN_SUCCESS;
94: }
95:
96: /*
97: * Routine: host_ipc_hash_info
98: * Purpose:
99: * Return information about the global reverse hash table.
100: * Conditions:
101: * Nothing locked. Obeys CountInOut protocol.
102: * Returns:
103: * KERN_SUCCESS Returned information.
104: * KERN_INVALID_HOST The host is null.
105: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
106: */
107:
108: kern_return_t
109: host_ipc_hash_info(
110: host_t host,
111: hash_info_bucket_array_t *infop,
112: mach_msg_type_number_t *countp)
113: {
114: vm_offset_t addr;
1.1.1.3 root 115: vm_size_t size = 0; /* Suppress gcc warning */
1.1 root 116: hash_info_bucket_t *info;
117: unsigned int potential, actual;
118: kern_return_t kr;
119:
120: if (host == HOST_NULL)
121: return KERN_INVALID_HOST;
122:
123: /* start with in-line data */
124:
125: info = *infop;
126: potential = *countp;
127:
128: for (;;) {
129: actual = ipc_hash_info(info, potential);
130: if (actual <= potential)
131: break;
132:
133: /* allocate more memory */
134:
135: if (info != *infop)
136: kmem_free(ipc_kernel_map, addr, size);
137:
138: size = round_page(actual * sizeof *info);
139: kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size);
140: if (kr != KERN_SUCCESS)
141: return KERN_RESOURCE_SHORTAGE;
142:
143: info = (hash_info_bucket_t *) addr;
144: potential = size/sizeof *info;
145: }
146:
147: if (info == *infop) {
148: /* data fit in-line; nothing to deallocate */
149:
150: *countp = actual;
151: } else if (actual == 0) {
152: kmem_free(ipc_kernel_map, addr, size);
153:
154: *countp = 0;
155: } else {
156: vm_map_copy_t copy;
157: vm_size_t used;
158:
159: used = round_page(actual * sizeof *info);
160:
161: if (used != size)
162: kmem_free(ipc_kernel_map, addr + used, size - used);
163:
164: kr = vm_map_copyin(ipc_kernel_map, addr, used,
165: TRUE, ©);
166: assert(kr == KERN_SUCCESS);
167:
168: *infop = (hash_info_bucket_t *) copy;
169: *countp = actual;
170: }
171:
172: return KERN_SUCCESS;
173: }
174:
175: /*
176: * Routine: host_ipc_marequest_info
177: * Purpose:
178: * Return information about the marequest hash table.
179: * Conditions:
180: * Nothing locked. Obeys CountInOut protocol.
181: * Returns:
182: * KERN_SUCCESS Returned information.
183: * KERN_INVALID_HOST The host is null.
184: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
185: */
186:
187: kern_return_t
1.1.1.4 ! root 188: host_ipc_marequest_info(
! 189: host_t host,
! 190: unsigned int *maxp,
! 191: hash_info_bucket_array_t *infop,
! 192: unsigned int *countp)
1.1 root 193: {
194: vm_offset_t addr;
195: vm_size_t size = 0; /* '=0' to shut up lint */
196: hash_info_bucket_t *info;
197: unsigned int potential, actual;
198: kern_return_t kr;
199:
200: if (host == HOST_NULL)
201: return KERN_INVALID_HOST;
202:
203: /* start with in-line data */
204:
205: info = *infop;
206: potential = *countp;
207:
208: for (;;) {
209: actual = ipc_marequest_info(maxp, info, potential);
210: if (actual <= potential)
211: break;
212:
213: /* allocate more memory */
214:
215: if (info != *infop)
216: kmem_free(ipc_kernel_map, addr, size);
217:
218: size = round_page(actual * sizeof *info);
219: kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size);
220: if (kr != KERN_SUCCESS)
221: return KERN_RESOURCE_SHORTAGE;
222:
223: info = (hash_info_bucket_t *) addr;
224: potential = size/sizeof *info;
225: }
226:
227: if (info == *infop) {
228: /* data fit in-line; nothing to deallocate */
229:
230: *countp = actual;
231: } else if (actual == 0) {
232: kmem_free(ipc_kernel_map, addr, size);
233:
234: *countp = 0;
235: } else {
236: vm_map_copy_t copy;
237: vm_size_t used;
238:
239: used = round_page(actual * sizeof *info);
240:
241: if (used != size)
242: kmem_free(ipc_kernel_map, addr + used, size - used);
243:
244: kr = vm_map_copyin(ipc_kernel_map, addr, used,
245: TRUE, ©);
246: assert(kr == KERN_SUCCESS);
247:
248: *infop = (hash_info_bucket_t *) copy;
249: *countp = actual;
250: }
251:
252: return KERN_SUCCESS;
253: }
254:
255: /*
256: * Routine: mach_port_space_info
257: * Purpose:
258: * Returns information about an IPC space.
259: * Conditions:
260: * Nothing locked. Obeys CountInOut protocol.
261: * Returns:
262: * KERN_SUCCESS Returned information.
263: * KERN_INVALID_TASK The space is null.
264: * KERN_INVALID_TASK The space is dead.
265: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
266: */
267:
268: kern_return_t
269: mach_port_space_info(
270: ipc_space_t space,
271: ipc_info_space_t *infop,
272: ipc_info_name_array_t *tablep,
273: mach_msg_type_number_t *tableCntp,
274: ipc_info_tree_name_array_t *treep,
275: mach_msg_type_number_t *treeCntp)
276: {
277: ipc_info_name_t *table_info;
278: unsigned int table_potential, table_actual;
279: vm_offset_t table_addr;
1.1.1.3 root 280: vm_size_t table_size = 0; /* Suppress gcc warning */
1.1 root 281: ipc_info_tree_name_t *tree_info;
282: unsigned int tree_potential, tree_actual;
283: vm_offset_t tree_addr;
1.1.1.3 root 284: vm_size_t tree_size = 0; /* Suppress gcc warning */
1.1 root 285: ipc_tree_entry_t tentry;
286: ipc_entry_t table;
287: ipc_entry_num_t tsize;
288: mach_port_index_t index;
289: kern_return_t kr;
290:
291: if (space == IS_NULL)
292: return KERN_INVALID_TASK;
293:
294: /* start with in-line memory */
295:
296: table_info = *tablep;
297: table_potential = *tableCntp;
298: tree_info = *treep;
299: tree_potential = *treeCntp;
300:
301: for (;;) {
302: is_read_lock(space);
303: if (!space->is_active) {
304: is_read_unlock(space);
305: if (table_info != *tablep)
306: kmem_free(ipc_kernel_map,
307: table_addr, table_size);
308: if (tree_info != *treep)
309: kmem_free(ipc_kernel_map,
310: tree_addr, tree_size);
311: return KERN_INVALID_TASK;
312: }
313:
314: table_actual = space->is_table_size;
315: tree_actual = space->is_tree_total;
316:
317: if ((table_actual <= table_potential) &&
318: (tree_actual <= tree_potential))
319: break;
320:
321: is_read_unlock(space);
322:
323: if (table_actual > table_potential) {
324: if (table_info != *tablep)
325: kmem_free(ipc_kernel_map,
326: table_addr, table_size);
327:
328: table_size = round_page(table_actual *
329: sizeof *table_info);
330: kr = kmem_alloc(ipc_kernel_map,
331: &table_addr, table_size);
332: if (kr != KERN_SUCCESS) {
333: if (tree_info != *treep)
334: kmem_free(ipc_kernel_map,
335: tree_addr, tree_size);
336:
337: return KERN_RESOURCE_SHORTAGE;
338: }
339:
340: table_info = (ipc_info_name_t *) table_addr;
341: table_potential = table_size/sizeof *table_info;
342: }
343:
344: if (tree_actual > tree_potential) {
345: if (tree_info != *treep)
346: kmem_free(ipc_kernel_map,
347: tree_addr, tree_size);
348:
349: tree_size = round_page(tree_actual *
350: sizeof *tree_info);
351: kr = kmem_alloc(ipc_kernel_map,
352: &tree_addr, tree_size);
353: if (kr != KERN_SUCCESS) {
354: if (table_info != *tablep)
355: kmem_free(ipc_kernel_map,
356: table_addr, table_size);
357:
358: return KERN_RESOURCE_SHORTAGE;
359: }
360:
361: tree_info = (ipc_info_tree_name_t *) tree_addr;
362: tree_potential = tree_size/sizeof *tree_info;
363: }
364: }
365: /* space is read-locked and active; we have enough wired memory */
366:
367: infop->iis_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD);
368: infop->iis_table_size = space->is_table_size;
369: infop->iis_table_next = space->is_table_next->its_size;
370: infop->iis_tree_size = space->is_tree_total;
371: infop->iis_tree_small = space->is_tree_small;
372: infop->iis_tree_hash = space->is_tree_hash;
373:
374: table = space->is_table;
375: tsize = space->is_table_size;
376:
377: for (index = 0; index < tsize; index++) {
378: ipc_info_name_t *iin = &table_info[index];
379: ipc_entry_t entry = &table[index];
380: ipc_entry_bits_t bits = entry->ie_bits;
381:
382: iin->iin_name = MACH_PORT_MAKEB(index, bits);
383: iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE;
384: iin->iin_compat = FALSE;
385: iin->iin_marequest = (bits & IE_BITS_MAREQUEST) ? TRUE : FALSE;
386: iin->iin_type = IE_BITS_TYPE(bits);
387: iin->iin_urefs = IE_BITS_UREFS(bits);
388: iin->iin_object = (vm_offset_t) entry->ie_object;
389: iin->iin_next = entry->ie_next;
390: iin->iin_hash = entry->ie_index;
391: }
392:
393: for (tentry = ipc_splay_traverse_start(&space->is_tree), index = 0;
394: tentry != ITE_NULL;
395: tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) {
396: ipc_info_tree_name_t *iitn = &tree_info[index++];
397: ipc_info_name_t *iin = &iitn->iitn_name;
398: ipc_entry_t entry = &tentry->ite_entry;
399: ipc_entry_bits_t bits = entry->ie_bits;
400:
401: assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE);
402:
403: iin->iin_name = tentry->ite_name;
404: iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE;
405: iin->iin_compat = FALSE;
406: iin->iin_marequest = (bits & IE_BITS_MAREQUEST) ? TRUE : FALSE;
407: iin->iin_type = IE_BITS_TYPE(bits);
408: iin->iin_urefs = IE_BITS_UREFS(bits);
409: iin->iin_object = (vm_offset_t) entry->ie_object;
410: iin->iin_next = entry->ie_next;
411: iin->iin_hash = entry->ie_index;
412:
413: if (tentry->ite_lchild == ITE_NULL)
414: iitn->iitn_lchild = MACH_PORT_NULL;
415: else
416: iitn->iitn_lchild = tentry->ite_lchild->ite_name;
417:
418: if (tentry->ite_rchild == ITE_NULL)
419: iitn->iitn_rchild = MACH_PORT_NULL;
420: else
421: iitn->iitn_rchild = tentry->ite_rchild->ite_name;
422:
423: }
424: ipc_splay_traverse_finish(&space->is_tree);
425: is_read_unlock(space);
426:
427: if (table_info == *tablep) {
428: /* data fit in-line; nothing to deallocate */
429:
430: *tableCntp = table_actual;
431: } else if (table_actual == 0) {
432: kmem_free(ipc_kernel_map, table_addr, table_size);
433:
434: *tableCntp = 0;
435: } else {
436: vm_size_t size_used, rsize_used;
437: vm_map_copy_t copy;
438:
439: /* kmem_alloc doesn't zero memory */
440:
441: size_used = table_actual * sizeof *table_info;
442: rsize_used = round_page(size_used);
443:
444: if (rsize_used != table_size)
445: kmem_free(ipc_kernel_map,
446: table_addr + rsize_used,
447: table_size - rsize_used);
448:
449: if (size_used != rsize_used)
1.1.1.4 ! root 450: memset((void *) (table_addr + size_used), 0,
1.1 root 451: rsize_used - size_used);
452:
453: kr = vm_map_copyin(ipc_kernel_map, table_addr, rsize_used,
454: TRUE, ©);
455:
456: assert(kr == KERN_SUCCESS);
457:
458: *tablep = (ipc_info_name_t *) copy;
459: *tableCntp = table_actual;
460: }
461:
462: if (tree_info == *treep) {
463: /* data fit in-line; nothing to deallocate */
464:
465: *treeCntp = tree_actual;
466: } else if (tree_actual == 0) {
467: kmem_free(ipc_kernel_map, tree_addr, tree_size);
468:
469: *treeCntp = 0;
470: } else {
471: vm_size_t size_used, rsize_used;
472: vm_map_copy_t copy;
473:
474: /* kmem_alloc doesn't zero memory */
475:
476: size_used = tree_actual * sizeof *tree_info;
477: rsize_used = round_page(size_used);
478:
479: if (rsize_used != tree_size)
480: kmem_free(ipc_kernel_map,
481: tree_addr + rsize_used,
482: tree_size - rsize_used);
483:
484: if (size_used != rsize_used)
1.1.1.4 ! root 485: memset((void *) (tree_addr + size_used), 0,
1.1 root 486: rsize_used - size_used);
487:
488: kr = vm_map_copyin(ipc_kernel_map, tree_addr, rsize_used,
489: TRUE, ©);
490:
491: assert(kr == KERN_SUCCESS);
492:
493: *treep = (ipc_info_tree_name_t *) copy;
494: *treeCntp = tree_actual;
495: }
496:
497: return KERN_SUCCESS;
498: }
499:
500: /*
501: * Routine: mach_port_dnrequest_info
502: * Purpose:
503: * Returns information about the dead-name requests
504: * registered with the named receive right.
505: * Conditions:
506: * Nothing locked.
507: * Returns:
508: * KERN_SUCCESS Retrieved information.
509: * KERN_INVALID_TASK The space is null.
510: * KERN_INVALID_TASK The space is dead.
511: * KERN_INVALID_NAME The name doesn't denote a right.
512: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
513: */
514:
515: kern_return_t
516: mach_port_dnrequest_info(
517: ipc_space_t space,
518: mach_port_t name,
519: unsigned int *totalp,
520: unsigned int *usedp)
521: {
522: unsigned int total, used;
523: ipc_port_t port;
524: kern_return_t kr;
525:
526: if (space == IS_NULL)
527: return KERN_INVALID_TASK;
528:
529: kr = ipc_port_translate_receive(space, name, &port);
530: if (kr != KERN_SUCCESS)
531: return kr;
532: /* port is locked and active */
533:
534: if (port->ip_dnrequests == IPR_NULL) {
535: total = 0;
536: used = 0;
537: } else {
538: ipc_port_request_t dnrequests = port->ip_dnrequests;
539: ipc_port_request_index_t index;
540:
541: total = dnrequests->ipr_size->its_size;
542:
543: for (index = 1, used = 0;
544: index < total; index++) {
545: ipc_port_request_t ipr = &dnrequests[index];
546:
547: if (ipr->ipr_name != MACH_PORT_NULL)
548: used++;
549: }
550: }
551: ip_unlock(port);
552:
553: *totalp = total;
554: *usedp = used;
555: return KERN_SUCCESS;
556: }
557:
558: /*
559: * Routine: mach_port_kernel_object [kernel call]
560: * Purpose:
561: * Retrieve the type and address of the kernel object
562: * represented by a send or receive right.
563: * Conditions:
564: * Nothing locked.
565: * Returns:
566: * KERN_SUCCESS Retrieved kernel object info.
567: * KERN_INVALID_TASK The space is null.
568: * KERN_INVALID_TASK The space is dead.
569: * KERN_INVALID_NAME The name doesn't denote a right.
570: * KERN_INVALID_RIGHT Name doesn't denote
571: * send or receive rights.
572: */
573:
574: kern_return_t
575: mach_port_kernel_object(
576: ipc_space_t space,
577: mach_port_t name,
578: unsigned int *typep,
579: vm_offset_t *addrp)
580: {
581: ipc_entry_t entry;
582: ipc_port_t port;
583: kern_return_t kr;
584:
585: kr = ipc_right_lookup_read(space, name, &entry);
586: if (kr != KERN_SUCCESS)
587: return kr;
588: /* space is read-locked and active */
589:
590: if ((entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE) == 0) {
591: is_read_unlock(space);
592: return KERN_INVALID_RIGHT;
593: }
594:
595: port = (ipc_port_t) entry->ie_object;
596: assert(port != IP_NULL);
597:
598: ip_lock(port);
599: is_read_unlock(space);
600:
601: if (!ip_active(port)) {
602: ip_unlock(port);
603: return KERN_INVALID_RIGHT;
604: }
605:
1.1.1.4 ! root 606: *typep = ip_kotype(port);
! 607: *addrp = port->ip_kobject;
1.1 root 608: ip_unlock(port);
609: return KERN_SUCCESS;
610: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.