|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990 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: ipc/mach_debug.c
30: * Author: Rich Draves
31: * Date: 1989
32: *
33: * Exported kernel calls. See mach_debug/mach_debug.defs.
34: */
35:
36: #include <mach_ipc_compat.h>
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;
115: vm_size_t size;
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
188: host_ipc_marequest_info(host, maxp, infop, countp)
189: host_t host;
190: unsigned int *maxp;
191: hash_info_bucket_array_t *infop;
192: unsigned int *countp;
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;
280: vm_size_t table_size;
281: ipc_info_tree_name_t *tree_info;
282: unsigned int tree_potential, tree_actual;
283: vm_offset_t tree_addr;
284: vm_size_t tree_size;
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: #if MACH_IPC_COMPAT
385: iin->iin_compat = (bits & IE_BITS_COMPAT) ? TRUE : FALSE;
386: #else /* MACH_IPC_COMPAT */
387: iin->iin_compat = FALSE;
388: #endif /* MACH_IPC_COMPAT */
389: iin->iin_marequest = (bits & IE_BITS_MAREQUEST) ? TRUE : FALSE;
390: iin->iin_type = IE_BITS_TYPE(bits);
391: iin->iin_urefs = IE_BITS_UREFS(bits);
392: iin->iin_object = (vm_offset_t) entry->ie_object;
393: iin->iin_next = entry->ie_next;
394: iin->iin_hash = entry->ie_index;
395: }
396:
397: for (tentry = ipc_splay_traverse_start(&space->is_tree), index = 0;
398: tentry != ITE_NULL;
399: tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) {
400: ipc_info_tree_name_t *iitn = &tree_info[index++];
401: ipc_info_name_t *iin = &iitn->iitn_name;
402: ipc_entry_t entry = &tentry->ite_entry;
403: ipc_entry_bits_t bits = entry->ie_bits;
404:
405: assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE);
406:
407: iin->iin_name = tentry->ite_name;
408: iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE;
409: #if MACH_IPC_COMPAT
410: iin->iin_compat = (bits & IE_BITS_COMPAT) ? TRUE : FALSE;
411: #else /* MACH_IPC_COMPAT */
412: iin->iin_compat = FALSE;
413: #endif /* MACH_IPC_COMPAT */
414: iin->iin_marequest = (bits & IE_BITS_MAREQUEST) ? TRUE : FALSE;
415: iin->iin_type = IE_BITS_TYPE(bits);
416: iin->iin_urefs = IE_BITS_UREFS(bits);
417: iin->iin_object = (vm_offset_t) entry->ie_object;
418: iin->iin_next = entry->ie_next;
419: iin->iin_hash = entry->ie_index;
420:
421: if (tentry->ite_lchild == ITE_NULL)
422: iitn->iitn_lchild = MACH_PORT_NULL;
423: else
424: iitn->iitn_lchild = tentry->ite_lchild->ite_name;
425:
426: if (tentry->ite_rchild == ITE_NULL)
427: iitn->iitn_rchild = MACH_PORT_NULL;
428: else
429: iitn->iitn_rchild = tentry->ite_rchild->ite_name;
430:
431: }
432: ipc_splay_traverse_finish(&space->is_tree);
433: is_read_unlock(space);
434:
435: if (table_info == *tablep) {
436: /* data fit in-line; nothing to deallocate */
437:
438: *tableCntp = table_actual;
439: } else if (table_actual == 0) {
440: kmem_free(ipc_kernel_map, table_addr, table_size);
441:
442: *tableCntp = 0;
443: } else {
444: vm_size_t size_used, rsize_used;
445: vm_map_copy_t copy;
446:
447: /* kmem_alloc doesn't zero memory */
448:
449: size_used = table_actual * sizeof *table_info;
450: rsize_used = round_page(size_used);
451:
452: if (rsize_used != table_size)
453: kmem_free(ipc_kernel_map,
454: table_addr + rsize_used,
455: table_size - rsize_used);
456:
457: if (size_used != rsize_used)
458: bzero((char *) (table_addr + size_used),
459: rsize_used - size_used);
460:
461: kr = vm_map_copyin(ipc_kernel_map, table_addr, rsize_used,
462: TRUE, ©);
463:
464: assert(kr == KERN_SUCCESS);
465:
466: *tablep = (ipc_info_name_t *) copy;
467: *tableCntp = table_actual;
468: }
469:
470: if (tree_info == *treep) {
471: /* data fit in-line; nothing to deallocate */
472:
473: *treeCntp = tree_actual;
474: } else if (tree_actual == 0) {
475: kmem_free(ipc_kernel_map, tree_addr, tree_size);
476:
477: *treeCntp = 0;
478: } else {
479: vm_size_t size_used, rsize_used;
480: vm_map_copy_t copy;
481:
482: /* kmem_alloc doesn't zero memory */
483:
484: size_used = tree_actual * sizeof *tree_info;
485: rsize_used = round_page(size_used);
486:
487: if (rsize_used != tree_size)
488: kmem_free(ipc_kernel_map,
489: tree_addr + rsize_used,
490: tree_size - rsize_used);
491:
492: if (size_used != rsize_used)
493: bzero((char *) (tree_addr + size_used),
494: rsize_used - size_used);
495:
496: kr = vm_map_copyin(ipc_kernel_map, tree_addr, rsize_used,
497: TRUE, ©);
498:
499: assert(kr == KERN_SUCCESS);
500:
501: *treep = (ipc_info_tree_name_t *) copy;
502: *treeCntp = tree_actual;
503: }
504:
505: return KERN_SUCCESS;
506: }
507:
508: /*
509: * Routine: mach_port_dnrequest_info
510: * Purpose:
511: * Returns information about the dead-name requests
512: * registered with the named receive right.
513: * Conditions:
514: * Nothing locked.
515: * Returns:
516: * KERN_SUCCESS Retrieved information.
517: * KERN_INVALID_TASK The space is null.
518: * KERN_INVALID_TASK The space is dead.
519: * KERN_INVALID_NAME The name doesn't denote a right.
520: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
521: */
522:
523: kern_return_t
524: mach_port_dnrequest_info(
525: ipc_space_t space,
526: mach_port_t name,
527: unsigned int *totalp,
528: unsigned int *usedp)
529: {
530: unsigned int total, used;
531: ipc_port_t port;
532: kern_return_t kr;
533:
534: if (space == IS_NULL)
535: return KERN_INVALID_TASK;
536:
537: kr = ipc_port_translate_receive(space, name, &port);
538: if (kr != KERN_SUCCESS)
539: return kr;
540: /* port is locked and active */
541:
542: if (port->ip_dnrequests == IPR_NULL) {
543: total = 0;
544: used = 0;
545: } else {
546: ipc_port_request_t dnrequests = port->ip_dnrequests;
547: ipc_port_request_index_t index;
548:
549: total = dnrequests->ipr_size->its_size;
550:
551: for (index = 1, used = 0;
552: index < total; index++) {
553: ipc_port_request_t ipr = &dnrequests[index];
554:
555: if (ipr->ipr_name != MACH_PORT_NULL)
556: used++;
557: }
558: }
559: ip_unlock(port);
560:
561: *totalp = total;
562: *usedp = used;
563: return KERN_SUCCESS;
564: }
565:
566: /*
567: * Routine: mach_port_kernel_object [kernel call]
568: * Purpose:
569: * Retrieve the type and address of the kernel object
570: * represented by a send or receive right.
571: * Conditions:
572: * Nothing locked.
573: * Returns:
574: * KERN_SUCCESS Retrieved kernel object info.
575: * KERN_INVALID_TASK The space is null.
576: * KERN_INVALID_TASK The space is dead.
577: * KERN_INVALID_NAME The name doesn't denote a right.
578: * KERN_INVALID_RIGHT Name doesn't denote
579: * send or receive rights.
580: */
581:
582: kern_return_t
583: mach_port_kernel_object(
584: ipc_space_t space,
585: mach_port_t name,
586: unsigned int *typep,
587: vm_offset_t *addrp)
588: {
589: ipc_entry_t entry;
590: ipc_port_t port;
591: kern_return_t kr;
592:
593: kr = ipc_right_lookup_read(space, name, &entry);
594: if (kr != KERN_SUCCESS)
595: return kr;
596: /* space is read-locked and active */
597:
598: if ((entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE) == 0) {
599: is_read_unlock(space);
600: return KERN_INVALID_RIGHT;
601: }
602:
603: port = (ipc_port_t) entry->ie_object;
604: assert(port != IP_NULL);
605:
606: ip_lock(port);
607: is_read_unlock(space);
608:
609: if (!ip_active(port)) {
610: ip_unlock(port);
611: return KERN_INVALID_RIGHT;
612: }
613:
614: *typep = (unsigned int) ip_kotype(port);
615: *addrp = (vm_offset_t) port->ip_kobject;
616: ip_unlock(port);
617: return KERN_SUCCESS;
618: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.