|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University.
4: * Copyright (c) 1993,1994 The University of Utah and
5: * the Computer Systems Laboratory (CSL).
6: * All rights reserved.
7: *
8: * Permission to use, copy, modify and distribute this software and its
9: * documentation is hereby granted, provided that both the copyright
10: * notice and this permission notice appear in all copies of the
11: * software, derivative works or modified versions, and any portions
12: * thereof, and that both notices appear in supporting documentation.
13: *
14: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
15: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
16: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
17: * THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or [email protected]
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie Mellon
27: * the rights to redistribute these changes.
28: */
29: /*
30: */
31: /*
32: * File: ipc/mach_port.c
33: * Author: Rich Draves
34: * Date: 1989
35: *
36: * Exported kernel calls. See mach/mach_port.defs.
37: */
38:
1.1.1.3 ! root 39: #include <kern/debug.h>
! 40: #include <kern/printf.h>
1.1 root 41: #include <mach/port.h>
42: #include <mach/kern_return.h>
43: #include <mach/notify.h>
44: #include <mach/mach_param.h>
45: #include <mach/vm_param.h>
46: #include <mach/vm_prot.h>
47: #ifdef MIGRATING_THREADS
48: #include <mach/rpc.h>
49: #include <kern/task.h>
50: #include <kern/act.h>
51: #endif /* MIGRATING_THREADS */
52: #include <vm/vm_map.h>
53: #include <vm/vm_kern.h>
54: #include <vm/vm_user.h>
55: #include <ipc/ipc_entry.h>
56: #include <ipc/ipc_space.h>
57: #include <ipc/ipc_object.h>
58: #include <ipc/ipc_notify.h>
59: #include <ipc/ipc_port.h>
60: #include <ipc/ipc_pset.h>
61: #include <ipc/ipc_right.h>
1.1.1.3 ! root 62: #include <ipc/mach_port.h>
1.1 root 63:
64:
65:
66: /*
67: * Routine: mach_port_names_helper
68: * Purpose:
69: * A helper function for mach_port_names.
70: */
71:
72: void
73: mach_port_names_helper(
74: ipc_port_timestamp_t timestamp,
75: ipc_entry_t entry,
76: mach_port_t name,
77: mach_port_t *names,
78: mach_port_type_t *types,
79: ipc_entry_num_t *actualp)
80: {
81: ipc_entry_bits_t bits = entry->ie_bits;
82: ipc_port_request_index_t request = entry->ie_request;
83: mach_port_type_t type;
84: ipc_entry_num_t actual;
85:
86: if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
87: ipc_port_t port;
88: boolean_t died;
89:
90: port = (ipc_port_t) entry->ie_object;
91: assert(port != IP_NULL);
92:
93: /*
94: * The timestamp serializes mach_port_names
95: * with ipc_port_destroy. If the port died,
96: * but after mach_port_names started, pretend
97: * that it isn't dead.
98: */
99:
100: ip_lock(port);
101: died = (!ip_active(port) &&
102: IP_TIMESTAMP_ORDER(port->ip_timestamp, timestamp));
103: ip_unlock(port);
104:
105: if (died) {
106: /* pretend this is a dead-name entry */
107:
108: bits &= ~(IE_BITS_TYPE_MASK|IE_BITS_MAREQUEST);
109: bits |= MACH_PORT_TYPE_DEAD_NAME;
110: if (request != 0)
111: bits++;
112: request = 0;
113: }
114: }
115:
116: type = IE_BITS_TYPE(bits);
117: if (request != 0)
118: type |= MACH_PORT_TYPE_DNREQUEST;
119: if (bits & IE_BITS_MAREQUEST)
120: type |= MACH_PORT_TYPE_MAREQUEST;
121:
122: actual = *actualp;
123: names[actual] = name;
124: types[actual] = type;
125: *actualp = actual+1;
126: }
127:
128: /*
129: * Routine: mach_port_names [kernel call]
130: * Purpose:
131: * Retrieves a list of the rights present in the space,
132: * along with type information. (Same as returned
133: * by mach_port_type.) The names are returned in
134: * no particular order, but they (and the type info)
135: * are an accurate snapshot of the space.
136: * Conditions:
137: * Nothing locked.
138: * Returns:
139: * KERN_SUCCESS Arrays of names and types returned.
140: * KERN_INVALID_TASK The space is null.
141: * KERN_INVALID_TASK The space is dead.
142: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
143: */
144:
145: kern_return_t
146: mach_port_names(
147: ipc_space_t space,
148: mach_port_t **namesp,
149: mach_msg_type_number_t *namesCnt,
150: mach_port_type_t **typesp,
151: mach_msg_type_number_t *typesCnt)
152: {
153: ipc_tree_entry_t tentry;
154: ipc_entry_t table;
155: ipc_entry_num_t tsize;
156: mach_port_index_t index;
157: ipc_entry_num_t actual; /* this many names */
158: ipc_port_timestamp_t timestamp; /* logical time of this operation */
159: mach_port_t *names;
160: mach_port_type_t *types;
161: kern_return_t kr;
162:
163: vm_size_t size; /* size of allocated memory */
164: vm_offset_t addr1; /* allocated memory, for names */
165: vm_offset_t addr2; /* allocated memory, for types */
166: vm_map_copy_t memory1; /* copied-in memory, for names */
167: vm_map_copy_t memory2; /* copied-in memory, for types */
168:
169: /* safe simplifying assumption */
170: assert_static(sizeof(mach_port_t) == sizeof(mach_port_type_t));
171:
172: if (space == IS_NULL)
173: return KERN_INVALID_TASK;
174:
175: size = 0;
176:
177: for (;;) {
178: ipc_entry_num_t bound;
179: vm_size_t size_needed;
180:
181: is_read_lock(space);
182: if (!space->is_active) {
183: is_read_unlock(space);
184: if (size != 0) {
185: kmem_free(ipc_kernel_map, addr1, size);
186: kmem_free(ipc_kernel_map, addr2, size);
187: }
188: return KERN_INVALID_TASK;
189: }
190:
191: /* upper bound on number of names in the space */
192:
193: bound = space->is_table_size + space->is_tree_total;
194: size_needed = round_page(bound * sizeof(mach_port_t));
195:
196: if (size_needed <= size)
197: break;
198:
199: is_read_unlock(space);
200:
201: if (size != 0) {
202: kmem_free(ipc_kernel_map, addr1, size);
203: kmem_free(ipc_kernel_map, addr2, size);
204: }
205: size = size_needed;
206:
207: kr = vm_allocate(ipc_kernel_map, &addr1, size, TRUE);
1.1.1.3 ! root 208: if (kr != KERN_SUCCESS) {
! 209: printf_once("no more room in ipc_kernel_map\n");
1.1 root 210: return KERN_RESOURCE_SHORTAGE;
1.1.1.3 ! root 211: }
1.1 root 212:
213: kr = vm_allocate(ipc_kernel_map, &addr2, size, TRUE);
214: if (kr != KERN_SUCCESS) {
1.1.1.3 ! root 215: printf_once("no more room in ipc_kernel_map\n");
1.1 root 216: kmem_free(ipc_kernel_map, addr1, size);
217: return KERN_RESOURCE_SHORTAGE;
218: }
219:
220: /* can't fault while we hold locks */
221:
222: kr = vm_map_pageable(ipc_kernel_map, addr1, addr1 + size,
223: VM_PROT_READ|VM_PROT_WRITE);
224: assert(kr == KERN_SUCCESS);
225:
226: kr = vm_map_pageable(ipc_kernel_map, addr2, addr2 + size,
227: VM_PROT_READ|VM_PROT_WRITE);
228: assert(kr == KERN_SUCCESS);
229: }
230: /* space is read-locked and active */
231:
232: names = (mach_port_t *) addr1;
233: types = (mach_port_type_t *) addr2;
234: actual = 0;
235:
236: timestamp = ipc_port_timestamp();
237:
238: table = space->is_table;
239: tsize = space->is_table_size;
240:
241: for (index = 0; index < tsize; index++) {
242: ipc_entry_t entry = &table[index];
243: ipc_entry_bits_t bits = entry->ie_bits;
244:
245: if (IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE) {
246: mach_port_t name = MACH_PORT_MAKEB(index, bits);
247:
248: mach_port_names_helper(timestamp, entry, name,
249: names, types, &actual);
250: }
251: }
252:
253: for (tentry = ipc_splay_traverse_start(&space->is_tree);
254: tentry != ITE_NULL;
255: tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) {
256: ipc_entry_t entry = &tentry->ite_entry;
257: mach_port_t name = tentry->ite_name;
258:
259: assert(IE_BITS_TYPE(tentry->ite_bits) != MACH_PORT_TYPE_NONE);
260:
261: mach_port_names_helper(timestamp, entry, name,
262: names, types, &actual);
263: }
264: ipc_splay_traverse_finish(&space->is_tree);
265: is_read_unlock(space);
266:
267: if (actual == 0) {
268: memory1 = VM_MAP_COPY_NULL;
269: memory2 = VM_MAP_COPY_NULL;
270:
271: if (size != 0) {
272: kmem_free(ipc_kernel_map, addr1, size);
273: kmem_free(ipc_kernel_map, addr2, size);
274: }
275: } else {
276: vm_size_t size_used;
277:
278: size_used = round_page(actual * sizeof(mach_port_t));
279:
280: /*
281: * Make used memory pageable and get it into
282: * copied-in form. Free any unused memory.
283: */
284:
285: kr = vm_map_pageable(ipc_kernel_map,
286: addr1, addr1 + size_used,
287: VM_PROT_NONE);
288: assert(kr == KERN_SUCCESS);
289:
290: kr = vm_map_pageable(ipc_kernel_map,
291: addr2, addr2 + size_used,
292: VM_PROT_NONE);
293: assert(kr == KERN_SUCCESS);
294:
295: kr = vm_map_copyin(ipc_kernel_map, addr1, size_used,
296: TRUE, &memory1);
297: assert(kr == KERN_SUCCESS);
298:
299: kr = vm_map_copyin(ipc_kernel_map, addr2, size_used,
300: TRUE, &memory2);
301: assert(kr == KERN_SUCCESS);
302:
303: if (size_used != size) {
304: kmem_free(ipc_kernel_map,
305: addr1 + size_used, size - size_used);
306: kmem_free(ipc_kernel_map,
307: addr2 + size_used, size - size_used);
308: }
309: }
310:
311: *namesp = (mach_port_t *) memory1;
312: *namesCnt = actual;
313: *typesp = (mach_port_type_t *) memory2;
314: *typesCnt = actual;
315: return KERN_SUCCESS;
316: }
317:
318: /*
319: * Routine: mach_port_type [kernel call]
320: * Purpose:
321: * Retrieves the type of a right in the space.
322: * The type is a bitwise combination of one or more
323: * of the following type bits:
324: * MACH_PORT_TYPE_SEND
325: * MACH_PORT_TYPE_RECEIVE
326: * MACH_PORT_TYPE_SEND_ONCE
327: * MACH_PORT_TYPE_PORT_SET
328: * MACH_PORT_TYPE_DEAD_NAME
329: * In addition, the following pseudo-type bits may be present:
330: * MACH_PORT_TYPE_DNREQUEST
331: * A dead-name notification is requested.
332: * MACH_PORT_TYPE_MAREQUEST
333: * The send/receive right is blocked;
334: * a msg-accepted notification is outstanding.
335: * MACH_PORT_TYPE_COMPAT
336: * This is a compatibility-mode right;
337: * when the port dies, it will disappear
338: * instead of turning into a dead-name.
339: * Conditions:
340: * Nothing locked.
341: * Returns:
342: * KERN_SUCCESS Type is returned.
343: * KERN_INVALID_TASK The space is null.
344: * KERN_INVALID_TASK The space is dead.
345: * KERN_INVALID_NAME The name doesn't denote a right.
346: */
347:
348: kern_return_t
349: mach_port_type(
350: ipc_space_t space,
351: mach_port_t name,
352: mach_port_type_t *typep)
353: {
354: mach_port_urefs_t urefs;
355: ipc_entry_t entry;
356: kern_return_t kr;
357:
358: if (space == IS_NULL)
359: return KERN_INVALID_TASK;
360:
361: kr = ipc_right_lookup_write(space, name, &entry);
362: if (kr != KERN_SUCCESS)
363: return kr;
364: /* space is write-locked and active */
365:
366: kr = ipc_right_info(space, name, entry, typep, &urefs);
367: if (kr == KERN_SUCCESS)
368: is_write_unlock(space);
369: /* space is unlocked */
370: return kr;
371: }
372:
373: /*
374: * Routine: mach_port_rename [kernel call]
375: * Purpose:
376: * Changes the name denoting a right,
377: * from oname to nname.
378: * Conditions:
379: * Nothing locked.
380: * Returns:
381: * KERN_SUCCESS The right is renamed.
382: * KERN_INVALID_TASK The space is null.
383: * KERN_INVALID_TASK The space is dead.
384: * KERN_INVALID_NAME The oname doesn't denote a right.
385: * KERN_INVALID_VALUE The nname isn't a legal name.
386: * KERN_NAME_EXISTS The nname already denotes a right.
387: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
388: */
389:
390: kern_return_t
391: mach_port_rename(
392: ipc_space_t space,
393: mach_port_t oname,
394: mach_port_t nname)
395: {
396: if (space == IS_NULL)
397: return KERN_INVALID_TASK;
398:
399: if (!MACH_PORT_VALID(nname))
400: return KERN_INVALID_VALUE;
401:
402: return ipc_object_rename(space, oname, nname);
403: }
404:
405: /*
406: * Routine: mach_port_allocate_name [kernel call]
407: * Purpose:
408: * Allocates a right in a space, using a specific name
409: * for the new right. Possible rights:
410: * MACH_PORT_RIGHT_RECEIVE
411: * MACH_PORT_RIGHT_PORT_SET
412: * MACH_PORT_RIGHT_DEAD_NAME
413: *
414: * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
415: * has no extant send or send-once rights and no queued
416: * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
417: * and its make-send count is 0. It is not a member of
418: * a port set. It has no registered no-senders or
419: * port-destroyed notification requests.
420: *
421: * A new port set has no members.
422: *
423: * A new dead name has one user reference.
424: * Conditions:
425: * Nothing locked.
426: * Returns:
427: * KERN_SUCCESS The right is allocated.
428: * KERN_INVALID_TASK The space is null.
429: * KERN_INVALID_TASK The space is dead.
430: * KERN_INVALID_VALUE The name isn't a legal name.
431: * KERN_INVALID_VALUE "right" isn't a legal kind of right.
432: * KERN_NAME_EXISTS The name already denotes a right.
433: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
434: */
435:
436: kern_return_t
437: mach_port_allocate_name(space, right, name)
438: ipc_space_t space;
439: mach_port_right_t right;
440: mach_port_t name;
441: {
442: kern_return_t kr;
443:
444: if (space == IS_NULL)
445: return KERN_INVALID_TASK;
446:
447: if (!MACH_PORT_VALID(name))
448: return KERN_INVALID_VALUE;
449:
450: switch (right) {
451: case MACH_PORT_RIGHT_RECEIVE: {
452: ipc_port_t port;
453:
454: kr = ipc_port_alloc_name(space, name, &port);
455: if (kr == KERN_SUCCESS)
456: ip_unlock(port);
457: break;
458: }
459:
460: case MACH_PORT_RIGHT_PORT_SET: {
461: ipc_pset_t pset;
462:
463: kr = ipc_pset_alloc_name(space, name, &pset);
464: if (kr == KERN_SUCCESS)
465: ips_unlock(pset);
466: break;
467: }
468:
469: case MACH_PORT_RIGHT_DEAD_NAME:
470: kr = ipc_object_alloc_dead_name(space, name);
471: break;
472:
473: default:
474: kr = KERN_INVALID_VALUE;
475: break;
476: }
477:
478: return kr;
479: }
480:
481: /*
482: * Routine: mach_port_allocate [kernel call]
483: * Purpose:
484: * Allocates a right in a space. Like mach_port_allocate_name,
485: * except that the implementation picks a name for the right.
486: * The name may be any legal name in the space that doesn't
487: * currently denote a right.
488: * Conditions:
489: * Nothing locked.
490: * Returns:
491: * KERN_SUCCESS The right is allocated.
492: * KERN_INVALID_TASK The space is null.
493: * KERN_INVALID_TASK The space is dead.
494: * KERN_INVALID_VALUE "right" isn't a legal kind of right.
495: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
496: * KERN_NO_SPACE No room in space for another right.
497: */
498:
499: kern_return_t
500: mach_port_allocate(space, right, namep)
501: ipc_space_t space;
502: mach_port_right_t right;
503: mach_port_t *namep;
504: {
505: kern_return_t kr;
506:
507: if (space == IS_NULL)
508: return KERN_INVALID_TASK;
509:
510: switch (right) {
511: case MACH_PORT_RIGHT_RECEIVE: {
512: ipc_port_t port;
513:
514: kr = ipc_port_alloc(space, namep, &port);
515: if (kr == KERN_SUCCESS)
516: ip_unlock(port);
517: break;
518: }
519:
520: case MACH_PORT_RIGHT_PORT_SET: {
521: ipc_pset_t pset;
522:
523: kr = ipc_pset_alloc(space, namep, &pset);
524: if (kr == KERN_SUCCESS)
525: ips_unlock(pset);
526: break;
527: }
528:
529: case MACH_PORT_RIGHT_DEAD_NAME:
530: kr = ipc_object_alloc_dead(space, namep);
531: break;
532:
533: default:
534: kr = KERN_INVALID_VALUE;
535: break;
536: }
537:
538: return (kr);
539: }
540:
541: /*
542: * Routine: mach_port_destroy [kernel call]
543: * Purpose:
544: * Cleans up and destroys all rights denoted by a name
545: * in a space. The destruction of a receive right
546: * destroys the port, unless a port-destroyed request
547: * has been made for it; the destruction of a port-set right
548: * destroys the port set.
549: * Conditions:
550: * Nothing locked.
551: * Returns:
552: * KERN_SUCCESS The name is destroyed.
553: * KERN_INVALID_TASK The space is null.
554: * KERN_INVALID_TASK The space is dead.
555: * KERN_INVALID_NAME The name doesn't denote a right.
556: */
557:
1.1.1.3 ! root 558: static volatile int mach_port_deallocate_debug = 0;
! 559:
1.1 root 560: kern_return_t
561: mach_port_destroy(
562: ipc_space_t space,
563: mach_port_t name)
564: {
565: ipc_entry_t entry;
566: kern_return_t kr;
567:
568: if (space == IS_NULL)
569: return KERN_INVALID_TASK;
570:
571: kr = ipc_right_lookup_write(space, name, &entry);
1.1.1.3 ! root 572: if (kr != KERN_SUCCESS) {
! 573: if (name != MACH_PORT_NULL && name != MACH_PORT_DEAD && space == current_space()) {
! 574: printf("task %p destroying an invalid port %lu, most probably a bug.\n", current_task(), name);
! 575: if (mach_port_deallocate_debug)
! 576: SoftDebugger("mach_port_deallocate");
! 577: }
1.1 root 578: return kr;
1.1.1.3 ! root 579: }
1.1 root 580: /* space is write-locked and active */
581:
582: kr = ipc_right_destroy(space, name, entry); /* unlocks space */
583: return kr;
584: }
585:
586: /*
587: * Routine: mach_port_deallocate [kernel call]
588: * Purpose:
589: * Deallocates a user reference from a send right,
590: * send-once right, or a dead-name right. May
591: * deallocate the right, if this is the last uref,
592: * and destroy the name, if it doesn't denote
593: * other rights.
594: * Conditions:
595: * Nothing locked.
596: * Returns:
597: * KERN_SUCCESS The uref is deallocated.
598: * KERN_INVALID_TASK The space is null.
599: * KERN_INVALID_TASK The space is dead.
600: * KERN_INVALID_NAME The name doesn't denote a right.
601: * KERN_INVALID_RIGHT The right isn't correct.
602: */
603:
604: kern_return_t
605: mach_port_deallocate(
606: ipc_space_t space,
607: mach_port_t name)
608: {
609: ipc_entry_t entry;
610: kern_return_t kr;
611:
612: if (space == IS_NULL)
613: return KERN_INVALID_TASK;
614:
615: kr = ipc_right_lookup_write(space, name, &entry);
1.1.1.3 ! root 616: if (kr != KERN_SUCCESS) {
! 617: if (name != MACH_PORT_NULL && name != MACH_PORT_DEAD && space == current_space()) {
! 618: printf("task %p deallocating an invalid port %lu, most probably a bug.\n", current_task(), name);
! 619: if (mach_port_deallocate_debug)
! 620: SoftDebugger("mach_port_deallocate");
! 621: }
1.1 root 622: return kr;
1.1.1.3 ! root 623: }
1.1 root 624: /* space is write-locked */
625:
626: kr = ipc_right_dealloc(space, name, entry); /* unlocks space */
627: return kr;
628: }
629:
630: /*
631: * Routine: mach_port_get_refs [kernel call]
632: * Purpose:
633: * Retrieves the number of user references held by a right.
634: * Receive rights, port-set rights, and send-once rights
635: * always have one user reference. Returns zero if the
636: * name denotes a right, but not the queried right.
637: * Conditions:
638: * Nothing locked.
639: * Returns:
640: * KERN_SUCCESS Number of urefs returned.
641: * KERN_INVALID_TASK The space is null.
642: * KERN_INVALID_TASK The space is dead.
643: * KERN_INVALID_VALUE "right" isn't a legal value.
644: * KERN_INVALID_NAME The name doesn't denote a right.
645: */
646:
647: kern_return_t
648: mach_port_get_refs(
649: ipc_space_t space,
650: mach_port_t name,
651: mach_port_right_t right,
652: mach_port_urefs_t *urefsp)
653: {
654: mach_port_type_t type;
655: mach_port_urefs_t urefs;
656: ipc_entry_t entry;
657: kern_return_t kr;
658:
659: if (space == IS_NULL)
660: return KERN_INVALID_TASK;
661:
662: if (right >= MACH_PORT_RIGHT_NUMBER)
663: return KERN_INVALID_VALUE;
664:
665: kr = ipc_right_lookup_write(space, name, &entry);
666: if (kr != KERN_SUCCESS)
667: return kr;
668: /* space is write-locked and active */
669:
670: kr = ipc_right_info(space, name, entry, &type, &urefs); /* unlocks */
671: if (kr != KERN_SUCCESS)
672: return kr; /* space is unlocked */
673: is_write_unlock(space);
674:
675: if (type & MACH_PORT_TYPE(right))
676: switch (right) {
677: case MACH_PORT_RIGHT_SEND_ONCE:
678: assert(urefs == 1);
679: /* fall-through */
680:
681: case MACH_PORT_RIGHT_PORT_SET:
682: case MACH_PORT_RIGHT_RECEIVE:
683: *urefsp = 1;
684: break;
685:
686: case MACH_PORT_RIGHT_DEAD_NAME:
687: case MACH_PORT_RIGHT_SEND:
688: assert(urefs > 0);
689: *urefsp = urefs;
690: break;
691:
692: default:
693: panic("mach_port_get_refs: strange rights");
694: }
695: else
696: *urefsp = 0;
697:
698: return kr;
699: }
700:
701: /*
702: * Routine: mach_port_mod_refs
703: * Purpose:
704: * Modifies the number of user references held by a right.
705: * The resulting number of user references must be non-negative.
706: * If it is zero, the right is deallocated. If the name
707: * doesn't denote other rights, it is destroyed.
708: * Conditions:
709: * Nothing locked.
710: * Returns:
711: * KERN_SUCCESS Modified number of urefs.
712: * KERN_INVALID_TASK The space is null.
713: * KERN_INVALID_TASK The space is dead.
714: * KERN_INVALID_VALUE "right" isn't a legal value.
715: * KERN_INVALID_NAME The name doesn't denote a right.
716: * KERN_INVALID_RIGHT Name doesn't denote specified right.
717: * KERN_INVALID_VALUE Impossible modification to urefs.
718: * KERN_UREFS_OVERFLOW Urefs would overflow.
719: */
720:
721: kern_return_t
722: mach_port_mod_refs(
723: ipc_space_t space,
724: mach_port_t name,
725: mach_port_right_t right,
726: mach_port_delta_t delta)
727: {
728: ipc_entry_t entry;
729: kern_return_t kr;
730:
731: if (space == IS_NULL)
732: return KERN_INVALID_TASK;
733:
734: if (right >= MACH_PORT_RIGHT_NUMBER)
735: return KERN_INVALID_VALUE;
736:
737: kr = ipc_right_lookup_write(space, name, &entry);
738: if (kr != KERN_SUCCESS)
739: return kr;
740: /* space is write-locked and active */
741:
742: kr = ipc_right_delta(space, name, entry, right, delta); /* unlocks */
743: return kr;
744: }
745:
746: /*
747: * Routine: old_mach_port_get_receive_status [kernel call]
748: * Purpose:
749: * Compatibility for code written before sequence numbers.
750: * Retrieves mucho info about a receive right.
751: * Conditions:
752: * Nothing locked.
753: * Returns:
754: * KERN_SUCCESS Retrieved status.
755: * KERN_INVALID_TASK The space is null.
756: * KERN_INVALID_TASK The space is dead.
757: * KERN_INVALID_NAME The name doesn't denote a right.
758: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
759: */
760:
761: kern_return_t
1.1.1.3 ! root 762: mach_port_get_receive_status(ipc_space_t, mach_port_t, mach_port_status_t *);
! 763: kern_return_t
1.1 root 764: old_mach_port_get_receive_status(space, name, statusp)
765: ipc_space_t space;
766: mach_port_t name;
767: old_mach_port_status_t *statusp;
768: {
769: mach_port_status_t status;
770: kern_return_t kr;
771:
772: kr = mach_port_get_receive_status(space, name, &status);
773: if (kr != KERN_SUCCESS)
774: return kr;
775:
776: statusp->mps_pset = status.mps_pset;
777: statusp->mps_mscount = status.mps_mscount;
778: statusp->mps_qlimit = status.mps_qlimit;
779: statusp->mps_msgcount = status.mps_msgcount;
780: statusp->mps_sorights = status.mps_sorights;
781: statusp->mps_srights = status.mps_srights;
782: statusp->mps_pdrequest = status.mps_pdrequest;
783: statusp->mps_nsrequest = status.mps_nsrequest;
784:
785: return KERN_SUCCESS;
786: }
787:
788: /*
789: * Routine: mach_port_set_qlimit [kernel call]
790: * Purpose:
791: * Changes a receive right's queue limit.
792: * The new queue limit must be between 0 and
793: * MACH_PORT_QLIMIT_MAX, inclusive.
794: * Conditions:
795: * Nothing locked.
796: * Returns:
797: * KERN_SUCCESS Set queue limit.
798: * KERN_INVALID_TASK The space is null.
799: * KERN_INVALID_TASK The space is dead.
800: * KERN_INVALID_NAME The name doesn't denote a right.
801: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
802: * KERN_INVALID_VALUE Illegal queue limit.
803: */
804:
805: kern_return_t
806: mach_port_set_qlimit(space, name, qlimit)
807: ipc_space_t space;
808: mach_port_t name;
809: mach_port_msgcount_t qlimit;
810: {
811: ipc_port_t port;
812: kern_return_t kr;
813:
814: if (space == IS_NULL)
815: return KERN_INVALID_TASK;
816:
817: if (qlimit > MACH_PORT_QLIMIT_MAX)
818: return KERN_INVALID_VALUE;
819:
820: kr = ipc_port_translate_receive(space, name, &port);
821: if (kr != KERN_SUCCESS)
822: return kr;
823: /* port is locked and active */
824:
825: ipc_port_set_qlimit(port, qlimit);
826:
827: ip_unlock(port);
828: return KERN_SUCCESS;
829: }
830:
831: /*
832: * Routine: mach_port_set_mscount [kernel call]
833: * Purpose:
834: * Changes a receive right's make-send count.
835: * Conditions:
836: * Nothing locked.
837: * Returns:
838: * KERN_SUCCESS Set make-send count.
839: * KERN_INVALID_TASK The space is null.
840: * KERN_INVALID_TASK The space is dead.
841: * KERN_INVALID_NAME The name doesn't denote a right.
842: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
843: */
844:
845: kern_return_t
846: mach_port_set_mscount(
847: ipc_space_t space,
848: mach_port_t name,
849: mach_port_mscount_t mscount)
850: {
851: ipc_port_t port;
852: kern_return_t kr;
853:
854: if (space == IS_NULL)
855: return KERN_INVALID_TASK;
856:
857: kr = ipc_port_translate_receive(space, name, &port);
858: if (kr != KERN_SUCCESS)
859: return kr;
860: /* port is locked and active */
861:
862: ipc_port_set_mscount(port, mscount);
863:
864: ip_unlock(port);
865: return KERN_SUCCESS;
866: }
867:
868: /*
869: * Routine: mach_port_set_seqno [kernel call]
870: * Purpose:
871: * Changes a receive right's sequence number.
872: * Conditions:
873: * Nothing locked.
874: * Returns:
875: * KERN_SUCCESS Set sequence number.
876: * KERN_INVALID_TASK The space is null.
877: * KERN_INVALID_TASK The space is dead.
878: * KERN_INVALID_NAME The name doesn't denote a right.
879: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
880: */
881:
882: kern_return_t
883: mach_port_set_seqno(
884: ipc_space_t space,
885: mach_port_t name,
886: mach_port_seqno_t seqno)
887: {
888: ipc_port_t port;
889: kern_return_t kr;
890:
891: if (space == IS_NULL)
892: return KERN_INVALID_TASK;
893:
894: kr = ipc_port_translate_receive(space, name, &port);
895: if (kr != KERN_SUCCESS)
896: return kr;
897: /* port is locked and active */
898:
899: ipc_port_set_seqno(port, seqno);
900:
901: ip_unlock(port);
902: return KERN_SUCCESS;
903: }
904:
905: /*
906: * Routine: mach_port_gst_helper
907: * Purpose:
908: * A helper function for mach_port_get_set_status.
909: */
910:
911: void
912: mach_port_gst_helper(
913: ipc_pset_t pset,
914: ipc_port_t port,
915: ipc_entry_num_t maxnames,
916: mach_port_t *names,
917: ipc_entry_num_t *actualp)
918: {
919: ipc_pset_t ip_pset;
920: mach_port_t name;
921:
922: assert(port != IP_NULL);
923:
924: ip_lock(port);
925: assert(ip_active(port));
926:
927: name = port->ip_receiver_name;
928: assert(name != MACH_PORT_NULL);
929: ip_pset = port->ip_pset;
930:
931: ip_unlock(port);
932:
933: if (pset == ip_pset) {
934: ipc_entry_num_t actual = *actualp;
935:
936: if (actual < maxnames)
937: names[actual] = name;
938:
939: *actualp = actual+1;
940: }
941: }
942:
943: /*
944: * Routine: mach_port_get_set_status [kernel call]
945: * Purpose:
946: * Retrieves a list of members in a port set.
947: * Returns the space's name for each receive right member.
948: * Conditions:
949: * Nothing locked.
950: * Returns:
951: * KERN_SUCCESS Retrieved list of members.
952: * KERN_INVALID_TASK The space is null.
953: * KERN_INVALID_TASK The space is dead.
954: * KERN_INVALID_NAME The name doesn't denote a right.
955: * KERN_INVALID_RIGHT Name doesn't denote a port set.
956: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
957: */
958:
959: kern_return_t
960: mach_port_get_set_status(
961: ipc_space_t space,
962: mach_port_t name,
963: mach_port_t **members,
964: mach_msg_type_number_t *membersCnt)
965: {
966: ipc_entry_num_t actual; /* this many members */
967: ipc_entry_num_t maxnames; /* space for this many members */
968: kern_return_t kr;
969:
970: vm_size_t size; /* size of allocated memory */
971: vm_offset_t addr; /* allocated memory */
972: vm_map_copy_t memory; /* copied-in memory */
973:
974: if (space == IS_NULL)
975: return KERN_INVALID_TASK;
976:
977: size = PAGE_SIZE; /* initial guess */
978:
979: for (;;) {
980: ipc_tree_entry_t tentry;
981: ipc_entry_t entry, table;
982: ipc_entry_num_t tsize;
983: mach_port_index_t index;
984: mach_port_t *names;
985: ipc_pset_t pset;
986:
987: kr = vm_allocate(ipc_kernel_map, &addr, size, TRUE);
1.1.1.3 ! root 988: if (kr != KERN_SUCCESS) {
! 989: printf_once("no more room in ipc_kernel_map\n");
1.1 root 990: return KERN_RESOURCE_SHORTAGE;
1.1.1.3 ! root 991: }
1.1 root 992:
993: /* can't fault while we hold locks */
994:
995: kr = vm_map_pageable(ipc_kernel_map, addr, addr + size,
996: VM_PROT_READ|VM_PROT_WRITE);
997: assert(kr == KERN_SUCCESS);
998:
999: kr = ipc_right_lookup_read(space, name, &entry);
1000: if (kr != KERN_SUCCESS) {
1001: kmem_free(ipc_kernel_map, addr, size);
1002: return kr;
1003: }
1004: /* space is read-locked and active */
1005:
1006: if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_PORT_SET) {
1007: is_read_unlock(space);
1008: kmem_free(ipc_kernel_map, addr, size);
1009: return KERN_INVALID_RIGHT;
1010: }
1011:
1012: pset = (ipc_pset_t) entry->ie_object;
1013: assert(pset != IPS_NULL);
1014: /* the port set must be active */
1015:
1016: names = (mach_port_t *) addr;
1017: maxnames = size / sizeof(mach_port_t);
1018: actual = 0;
1019:
1020: table = space->is_table;
1021: tsize = space->is_table_size;
1022:
1023: for (index = 0; index < tsize; index++) {
1024: ipc_entry_t ientry = &table[index];
1025: ipc_entry_bits_t bits = ientry->ie_bits;
1026:
1027: if (bits & MACH_PORT_TYPE_RECEIVE) {
1028: ipc_port_t port =
1029: (ipc_port_t) ientry->ie_object;
1030:
1031: mach_port_gst_helper(pset, port, maxnames,
1032: names, &actual);
1033: }
1034: }
1035:
1036: for (tentry = ipc_splay_traverse_start(&space->is_tree);
1037: tentry != ITE_NULL;
1038: tentry = ipc_splay_traverse_next(&space->is_tree,FALSE)) {
1039: ipc_entry_bits_t bits = tentry->ite_bits;
1040:
1041: assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE);
1042:
1043: if (bits & MACH_PORT_TYPE_RECEIVE) {
1044: ipc_port_t port =
1045: (ipc_port_t) tentry->ite_object;
1046:
1047: mach_port_gst_helper(pset, port, maxnames,
1048: names, &actual);
1049: }
1050: }
1051: ipc_splay_traverse_finish(&space->is_tree);
1052: is_read_unlock(space);
1053:
1054: if (actual <= maxnames)
1055: break;
1056:
1057: /* didn't have enough memory; allocate more */
1058:
1059: kmem_free(ipc_kernel_map, addr, size);
1060: size = round_page(actual * sizeof(mach_port_t)) + PAGE_SIZE;
1061: }
1062:
1063: if (actual == 0) {
1064: memory = VM_MAP_COPY_NULL;
1065:
1066: kmem_free(ipc_kernel_map, addr, size);
1067: } else {
1068: vm_size_t size_used;
1069:
1070: size_used = round_page(actual * sizeof(mach_port_t));
1071:
1072: /*
1073: * Make used memory pageable and get it into
1074: * copied-in form. Free any unused memory.
1075: */
1076:
1077: kr = vm_map_pageable(ipc_kernel_map,
1078: addr, addr + size_used,
1079: VM_PROT_NONE);
1080: assert(kr == KERN_SUCCESS);
1081:
1082: kr = vm_map_copyin(ipc_kernel_map, addr, size_used,
1083: TRUE, &memory);
1084: assert(kr == KERN_SUCCESS);
1085:
1086: if (size_used != size)
1087: kmem_free(ipc_kernel_map,
1088: addr + size_used, size - size_used);
1089: }
1090:
1091: *members = (mach_port_t *) memory;
1092: *membersCnt = actual;
1093: return KERN_SUCCESS;
1094: }
1095:
1096: /*
1097: * Routine: mach_port_move_member [kernel call]
1098: * Purpose:
1099: * If after is MACH_PORT_NULL, removes member
1100: * from the port set it is in. Otherwise, adds
1101: * member to after, removing it from any set
1102: * it might already be in.
1103: * Conditions:
1104: * Nothing locked.
1105: * Returns:
1106: * KERN_SUCCESS Moved the port.
1107: * KERN_INVALID_TASK The space is null.
1108: * KERN_INVALID_TASK The space is dead.
1109: * KERN_INVALID_NAME Member didn't denote a right.
1110: * KERN_INVALID_RIGHT Member didn't denote a receive right.
1111: * KERN_INVALID_NAME After didn't denote a right.
1112: * KERN_INVALID_RIGHT After didn't denote a port set right.
1113: * KERN_NOT_IN_SET
1114: * After is MACH_PORT_NULL and Member isn't in a port set.
1115: */
1116:
1117: kern_return_t
1118: mach_port_move_member(
1119: ipc_space_t space,
1120: mach_port_t member,
1121: mach_port_t after)
1122: {
1123: ipc_entry_t entry;
1124: ipc_port_t port;
1125: ipc_pset_t nset;
1126: kern_return_t kr;
1127:
1128: if (space == IS_NULL)
1129: return KERN_INVALID_TASK;
1130:
1131: kr = ipc_right_lookup_read(space, member, &entry);
1132: if (kr != KERN_SUCCESS)
1133: return kr;
1134: /* space is read-locked and active */
1135:
1136: if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) {
1137: is_read_unlock(space);
1138: return KERN_INVALID_RIGHT;
1139: }
1140:
1141: port = (ipc_port_t) entry->ie_object;
1142: assert(port != IP_NULL);
1143:
1144: if (after == MACH_PORT_NULL)
1145: nset = IPS_NULL;
1146: else {
1147: entry = ipc_entry_lookup(space, after);
1148: if (entry == IE_NULL) {
1149: is_read_unlock(space);
1150: return KERN_INVALID_NAME;
1151: }
1152:
1153: if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) {
1154: is_read_unlock(space);
1155: return KERN_INVALID_RIGHT;
1156: }
1157:
1158: nset = (ipc_pset_t) entry->ie_object;
1159: assert(nset != IPS_NULL);
1160: }
1161:
1162: kr = ipc_pset_move(space, port, nset);
1163: /* space is unlocked */
1164: return kr;
1165: }
1166:
1167: /*
1168: * Routine: mach_port_request_notification [kernel call]
1169: * Purpose:
1170: * Requests a notification. The caller supplies
1171: * a send-once right for the notification to use,
1172: * and the call returns the previously registered
1173: * send-once right, if any. Possible types:
1174: *
1175: * MACH_NOTIFY_PORT_DESTROYED
1176: * Requests a port-destroyed notification
1177: * for a receive right. Sync should be zero.
1178: * MACH_NOTIFY_NO_SENDERS
1179: * Requests a no-senders notification for a
1180: * receive right. If there are currently no
1181: * senders, sync is less than or equal to the
1182: * current make-send count, and a send-once right
1183: * is supplied, then an immediate no-senders
1184: * notification is generated.
1185: * MACH_NOTIFY_DEAD_NAME
1186: * Requests a dead-name notification for a send
1187: * or receive right. If the name is already a
1188: * dead name, sync is non-zero, and a send-once
1189: * right is supplied, then an immediate dead-name
1190: * notification is generated.
1191: * Conditions:
1192: * Nothing locked.
1193: * Returns:
1194: * KERN_SUCCESS Requested a notification.
1195: * KERN_INVALID_TASK The space is null.
1196: * KERN_INVALID_TASK The space is dead.
1197: * KERN_INVALID_VALUE Bad id value.
1198: * KERN_INVALID_NAME Name doesn't denote a right.
1199: * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1200: * KERN_INVALID_CAPABILITY The notify port is dead.
1201: * MACH_NOTIFY_PORT_DESTROYED:
1202: * KERN_INVALID_VALUE Sync isn't zero.
1203: * MACH_NOTIFY_DEAD_NAME:
1204: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1205: * KERN_INVALID_ARGUMENT Name denotes dead name, but
1206: * sync is zero or notify is IP_NULL.
1207: * KERN_UREFS_OVERFLOW Name denotes dead name, but
1208: * generating immediate notif. would overflow urefs.
1209: */
1210:
1211: kern_return_t
1212: mach_port_request_notification(
1213: ipc_space_t space,
1214: mach_port_t name,
1215: mach_msg_id_t id,
1216: mach_port_mscount_t sync,
1217: ipc_port_t notify,
1218: ipc_port_t *previousp)
1219: {
1220: kern_return_t kr;
1221:
1222: if (space == IS_NULL)
1223: return KERN_INVALID_TASK;
1224:
1225: if (notify == IP_DEAD)
1226: return KERN_INVALID_CAPABILITY;
1227:
1228: switch (id) {
1229: case MACH_NOTIFY_PORT_DESTROYED: {
1230: ipc_port_t port, previous;
1231:
1232: if (sync != 0)
1233: return KERN_INVALID_VALUE;
1234:
1235: kr = ipc_port_translate_receive(space, name, &port);
1236: if (kr != KERN_SUCCESS)
1237: return kr;
1238: /* port is locked and active */
1239:
1240: ipc_port_pdrequest(port, notify, &previous);
1241: /* port is unlocked */
1242:
1243: *previousp = previous;
1244: break;
1245: }
1246:
1247: case MACH_NOTIFY_NO_SENDERS: {
1248: ipc_port_t port;
1249:
1250: kr = ipc_port_translate_receive(space, name, &port);
1251: if (kr != KERN_SUCCESS)
1252: return kr;
1253: /* port is locked and active */
1254:
1255: ipc_port_nsrequest(port, sync, notify, previousp);
1256: /* port is unlocked */
1257: break;
1258: }
1259:
1260: case MACH_NOTIFY_DEAD_NAME:
1261: kr = ipc_right_dnrequest(space, name, sync != 0,
1262: notify, previousp);
1263: if (kr != KERN_SUCCESS)
1264: return kr;
1265: break;
1266:
1267: default:
1268: return KERN_INVALID_VALUE;
1269: }
1270:
1271: return KERN_SUCCESS;
1272: }
1273:
1274: /*
1275: * Routine: mach_port_insert_right [kernel call]
1276: * Purpose:
1277: * Inserts a right into a space, as if the space
1278: * voluntarily received the right in a message,
1279: * except that the right gets the specified name.
1280: * Conditions:
1281: * Nothing locked.
1282: * Returns:
1283: * KERN_SUCCESS Inserted the right.
1284: * KERN_INVALID_TASK The space is null.
1285: * KERN_INVALID_TASK The space is dead.
1286: * KERN_INVALID_VALUE The name isn't a legal name.
1287: * KERN_NAME_EXISTS The name already denotes a right.
1288: * KERN_INVALID_VALUE Message doesn't carry a port right.
1289: * KERN_INVALID_CAPABILITY Port is null or dead.
1290: * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1291: * KERN_RIGHT_EXISTS Space has rights under another name.
1292: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1293: */
1294:
1295: kern_return_t
1296: mach_port_insert_right(
1297: ipc_space_t space,
1298: mach_port_t name,
1299: ipc_port_t poly,
1300: mach_msg_type_name_t polyPoly)
1301: {
1302: if (space == IS_NULL)
1303: return KERN_INVALID_TASK;
1304:
1305: if (!MACH_PORT_VALID(name) ||
1306: !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly))
1307: return KERN_INVALID_VALUE;
1308:
1.1.1.3 ! root 1309: if (!IO_VALID((ipc_object_t)poly))
1.1 root 1310: return KERN_INVALID_CAPABILITY;
1311:
1.1.1.3 ! root 1312: return ipc_object_copyout_name(space, (ipc_object_t)poly,
! 1313: polyPoly, FALSE, name);
1.1 root 1314: }
1315:
1316: /*
1317: * Routine: mach_port_extract_right [kernel call]
1318: * Purpose:
1319: * Extracts a right from a space, as if the space
1320: * voluntarily sent the right to the caller.
1321: * Conditions:
1322: * Nothing locked.
1323: * Returns:
1324: * KERN_SUCCESS Extracted the right.
1325: * KERN_INVALID_TASK The space is null.
1326: * KERN_INVALID_TASK The space is dead.
1327: * KERN_INVALID_VALUE Requested type isn't a port right.
1328: * KERN_INVALID_NAME Name doesn't denote a right.
1329: * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1330: */
1331:
1332: kern_return_t
1333: mach_port_extract_right(
1334: ipc_space_t space,
1335: mach_port_t name,
1336: mach_msg_type_name_t msgt_name,
1337: ipc_port_t *poly,
1338: mach_msg_type_name_t *polyPoly)
1339: {
1340: kern_return_t kr;
1341:
1342: if (space == IS_NULL)
1343: return KERN_INVALID_TASK;
1344:
1345: if (!MACH_MSG_TYPE_PORT_ANY(msgt_name))
1346: return KERN_INVALID_VALUE;
1347:
1348: kr = ipc_object_copyin(space, name, msgt_name, (ipc_object_t *) poly);
1349:
1350: if (kr == KERN_SUCCESS)
1351: *polyPoly = ipc_object_copyin_type(msgt_name);
1352: return kr;
1353: }
1354:
1355: /*
1356: * Routine: mach_port_get_receive_status [kernel call]
1357: * Purpose:
1358: * Retrieves mucho info about a receive right.
1359: * Conditions:
1360: * Nothing locked.
1361: * Returns:
1362: * KERN_SUCCESS Retrieved status.
1363: * KERN_INVALID_TASK The space is null.
1364: * KERN_INVALID_TASK The space is dead.
1365: * KERN_INVALID_NAME The name doesn't denote a right.
1366: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1367: */
1368:
1369: kern_return_t
1370: mach_port_get_receive_status(space, name, statusp)
1371: ipc_space_t space;
1372: mach_port_t name;
1373: mach_port_status_t *statusp;
1374: {
1375: ipc_port_t port;
1376: kern_return_t kr;
1377:
1378: if (space == IS_NULL)
1379: return KERN_INVALID_TASK;
1380:
1381: kr = ipc_port_translate_receive(space, name, &port);
1382: if (kr != KERN_SUCCESS)
1383: return kr;
1384: /* port is locked and active */
1385:
1386: if (port->ip_pset != IPS_NULL) {
1387: ipc_pset_t pset = port->ip_pset;
1388:
1389: ips_lock(pset);
1390: if (!ips_active(pset)) {
1391: ipc_pset_remove(pset, port);
1392: ips_check_unlock(pset);
1393: goto no_port_set;
1394: } else {
1395: statusp->mps_pset = pset->ips_local_name;
1396: imq_lock(&pset->ips_messages);
1397: statusp->mps_seqno = port->ip_seqno;
1398: imq_unlock(&pset->ips_messages);
1399: ips_unlock(pset);
1400: assert(MACH_PORT_VALID(statusp->mps_pset));
1401: }
1402: } else {
1403: no_port_set:
1404: statusp->mps_pset = MACH_PORT_NULL;
1405: imq_lock(&port->ip_messages);
1406: statusp->mps_seqno = port->ip_seqno;
1407: imq_unlock(&port->ip_messages);
1408: }
1409:
1410: statusp->mps_mscount = port->ip_mscount;
1411: statusp->mps_qlimit = port->ip_qlimit;
1412: statusp->mps_msgcount = port->ip_msgcount;
1413: statusp->mps_sorights = port->ip_sorights;
1414: statusp->mps_srights = port->ip_srights > 0;
1415: statusp->mps_pdrequest = port->ip_pdrequest != IP_NULL;
1416: statusp->mps_nsrequest = port->ip_nsrequest != IP_NULL;
1417: ip_unlock(port);
1418:
1419: return KERN_SUCCESS;
1420: }
1421:
1422: #ifdef MIGRATING_THREADS
1423: kern_return_t
1424: mach_port_set_rpcinfo(space, name, rpc_info, rpc_info_count)
1425: ipc_space_t space;
1426: mach_port_t name;
1427: void *rpc_info;
1428: unsigned int rpc_info_count;
1429: {
1430: ipc_target_t target;
1431: ipc_object_t object;
1432: kern_return_t kr;
1433:
1434: if (space == IS_NULL)
1435: return KERN_INVALID_TASK;
1436:
1437: kr = ipc_object_translate(space, name,
1438: MACH_PORT_RIGHT_PORT_SET, &object);
1439: if (kr == KERN_SUCCESS)
1440: target = &((ipc_pset_t)object)->ips_target;
1441: else {
1442: kr = ipc_object_translate(space, name,
1443: MACH_PORT_RIGHT_RECEIVE, &object);
1444: if (kr != KERN_SUCCESS)
1445: return kr;
1446: target = &((ipc_port_t)object)->ip_target;
1447: }
1448:
1449: /* port/pset is locked and active */
1450:
1451: kr = port_machine_set_rpcinfo(target, rpc_info, rpc_info_count);
1452:
1453: io_unlock(object);
1454:
1455: return kr;
1456: }
1457:
1458: #if 1
1459: int sacts, maxsacts;
1460: #endif
1461:
1462: sact_count()
1463: {
1464: printf("%d server activations in use, %d max\n", sacts, maxsacts);
1465: }
1466:
1467: kern_return_t
1468: mach_port_create_act(task, name, user_stack, user_rbuf, user_rbuf_size, out_act)
1469: task_t task;
1470: mach_port_t name;
1471: vm_offset_t user_stack;
1472: vm_offset_t user_rbuf;
1473: vm_size_t user_rbuf_size;
1474: Act **out_act;
1475: {
1476: ipc_target_t target;
1477: ipc_space_t space;
1478: ipc_object_t object;
1479: kern_return_t kr;
1480: Act *act;
1481:
1482: if (task == 0)
1483: return KERN_INVALID_TASK;
1484:
1485: /* First create the new activation. */
1486: kr = act_create(task, user_stack, user_rbuf, user_rbuf_size, &act);
1487: if (kr != KERN_SUCCESS)
1488: return kr;
1489:
1490: space = task->itk_space;
1491:
1492: kr = ipc_object_translate(space, name,
1493: MACH_PORT_RIGHT_PORT_SET, &object);
1494: if (kr == KERN_SUCCESS)
1495: target = &((ipc_pset_t)object)->ips_target;
1496: else {
1497: kr = ipc_object_translate(space, name,
1498: MACH_PORT_RIGHT_RECEIVE, &object);
1499: if (kr != KERN_SUCCESS) {
1500: act_terminate(act);
1501: act_deallocate(act);
1502: return kr;
1503: }
1504: target = &((ipc_port_t)object)->ip_target;
1505: }
1506:
1507: /* port/pset is locked and active */
1508: #if 0
1509: printf("act port/pset %08x ipc_target %08x stack %08x act %08x\n",
1510: object, target, user_stack, act);
1511: #endif
1512:
1513: /* Assign the activation to the port's actpool. */
1514: kr = act_set_target(act, target);
1515: if (kr != KERN_SUCCESS) {
1516: io_unlock(object);
1517: act_terminate(act);
1518: act_deallocate(act);
1519: return kr;
1520: }
1521: #if 0
1522: printf(" actpool %08x act %08x\n", target->ip_actpool, act);
1523: #endif
1524:
1525: io_unlock(object);
1526:
1527: /* Pass our reference to the activation back to the user. */
1528: *out_act = act;
1529:
1530: #if 1
1531: sacts++;
1532: if (sacts > maxsacts)
1533: maxsacts = sacts;
1534: act->mact.pcb->ss.mpsfu_high = 0x69;
1535: #endif
1536: return KERN_SUCCESS;
1537: }
1538:
1539: #ifdef RPCKERNELSIG
1540: kern_return_t
1541: mach_port_set_syscall_right(task, name)
1542: task_t task;
1543: mach_port_t name;
1544: {
1545: ipc_entry_t entry;
1546: kern_return_t kr;
1547:
1548: if (task == IS_NULL)
1549: return KERN_INVALID_TASK;
1550:
1551: kr = ipc_right_lookup_write(task, name, &entry);
1552: if (kr != KERN_SUCCESS) {
1553: return kr;
1554: }
1555:
1556: if (!(entry->ie_bits & MACH_PORT_TYPE(MACH_PORT_RIGHT_SEND))) {
1557: is_write_unlock(space);
1558: return KERN_INVALID_RIGHT;
1559: }
1560:
1561: task->syscall_ipc_entry = *entry;
1562:
1563: is_write_unlock(space);
1564:
1565: return KERN_SUCCESS;
1566: }
1567: #endif
1568: #endif /* MIGRATING_THREADS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.