|
|
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
1.1.1.4 ! root 437: mach_port_allocate_name(
! 438: ipc_space_t space,
! 439: mach_port_right_t right,
! 440: mach_port_t name)
1.1 root 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
1.1.1.4 ! root 500: mach_port_allocate(
! 501: ipc_space_t space,
! 502: mach_port_right_t right,
! 503: mach_port_t *namep)
1.1 root 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.4 ! root 558: static volatile boolean_t mach_port_deallocate_debug = FALSE;
1.1.1.3 root 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) {
1.1.1.4 ! root 573: if (MACH_PORT_VALID (name) && space == current_space()) {
! 574: printf("task %.*s destroying a bogus port %lu, most probably a bug.\n", sizeof current_task()->name, current_task()->name, name);
1.1.1.3 root 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) {
1.1.1.4 ! root 617: if (MACH_PORT_VALID (name) && space == current_space()) {
! 618: printf("task %.*s deallocating a bogus port %lu, most probably a bug.\n", sizeof current_task()->name, current_task()->name, name);
1.1.1.3 root 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);
1.1.1.4 ! root 738: if (kr != KERN_SUCCESS) {
! 739: if (MACH_PORT_VALID (name) && space == current_space()) {
! 740: printf("task %.*s %screasing a bogus port "
! 741: "%lu by %d, most probably a bug.\n",
! 742: sizeof current_task()->name,
! 743: current_task()->name,
! 744: delta < 0 ? "de" : "in", name,
! 745: delta < 0 ? -delta : delta);
! 746: if (mach_port_deallocate_debug)
! 747: SoftDebugger("mach_port_mod_refs");
! 748: }
1.1 root 749: return kr;
1.1.1.4 ! root 750: }
1.1 root 751: /* space is write-locked and active */
752:
753: kr = ipc_right_delta(space, name, entry, right, delta); /* unlocks */
754: return kr;
755: }
756:
757: /*
758: * Routine: mach_port_set_qlimit [kernel call]
759: * Purpose:
760: * Changes a receive right's queue limit.
761: * The new queue limit must be between 0 and
762: * MACH_PORT_QLIMIT_MAX, inclusive.
763: * Conditions:
764: * Nothing locked.
765: * Returns:
766: * KERN_SUCCESS Set queue limit.
767: * KERN_INVALID_TASK The space is null.
768: * KERN_INVALID_TASK The space is dead.
769: * KERN_INVALID_NAME The name doesn't denote a right.
770: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
771: * KERN_INVALID_VALUE Illegal queue limit.
772: */
773:
774: kern_return_t
1.1.1.4 ! root 775: mach_port_set_qlimit(
! 776: ipc_space_t space,
! 777: mach_port_t name,
! 778: mach_port_msgcount_t qlimit)
1.1 root 779: {
780: ipc_port_t port;
781: kern_return_t kr;
782:
783: if (space == IS_NULL)
784: return KERN_INVALID_TASK;
785:
786: if (qlimit > MACH_PORT_QLIMIT_MAX)
787: return KERN_INVALID_VALUE;
788:
789: kr = ipc_port_translate_receive(space, name, &port);
790: if (kr != KERN_SUCCESS)
791: return kr;
792: /* port is locked and active */
793:
794: ipc_port_set_qlimit(port, qlimit);
795:
796: ip_unlock(port);
797: return KERN_SUCCESS;
798: }
799:
800: /*
801: * Routine: mach_port_set_mscount [kernel call]
802: * Purpose:
803: * Changes a receive right's make-send count.
804: * Conditions:
805: * Nothing locked.
806: * Returns:
807: * KERN_SUCCESS Set make-send count.
808: * KERN_INVALID_TASK The space is null.
809: * KERN_INVALID_TASK The space is dead.
810: * KERN_INVALID_NAME The name doesn't denote a right.
811: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
812: */
813:
814: kern_return_t
815: mach_port_set_mscount(
816: ipc_space_t space,
817: mach_port_t name,
818: mach_port_mscount_t mscount)
819: {
820: ipc_port_t port;
821: kern_return_t kr;
822:
823: if (space == IS_NULL)
824: return KERN_INVALID_TASK;
825:
826: kr = ipc_port_translate_receive(space, name, &port);
827: if (kr != KERN_SUCCESS)
828: return kr;
829: /* port is locked and active */
830:
831: ipc_port_set_mscount(port, mscount);
832:
833: ip_unlock(port);
834: return KERN_SUCCESS;
835: }
836:
837: /*
838: * Routine: mach_port_set_seqno [kernel call]
839: * Purpose:
840: * Changes a receive right's sequence number.
841: * Conditions:
842: * Nothing locked.
843: * Returns:
844: * KERN_SUCCESS Set sequence number.
845: * KERN_INVALID_TASK The space is null.
846: * KERN_INVALID_TASK The space is dead.
847: * KERN_INVALID_NAME The name doesn't denote a right.
848: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
849: */
850:
851: kern_return_t
852: mach_port_set_seqno(
853: ipc_space_t space,
854: mach_port_t name,
855: mach_port_seqno_t seqno)
856: {
857: ipc_port_t port;
858: kern_return_t kr;
859:
860: if (space == IS_NULL)
861: return KERN_INVALID_TASK;
862:
863: kr = ipc_port_translate_receive(space, name, &port);
864: if (kr != KERN_SUCCESS)
865: return kr;
866: /* port is locked and active */
867:
868: ipc_port_set_seqno(port, seqno);
869:
870: ip_unlock(port);
871: return KERN_SUCCESS;
872: }
873:
874: /*
875: * Routine: mach_port_gst_helper
876: * Purpose:
877: * A helper function for mach_port_get_set_status.
878: */
879:
880: void
881: mach_port_gst_helper(
882: ipc_pset_t pset,
883: ipc_port_t port,
884: ipc_entry_num_t maxnames,
885: mach_port_t *names,
886: ipc_entry_num_t *actualp)
887: {
888: ipc_pset_t ip_pset;
889: mach_port_t name;
890:
891: assert(port != IP_NULL);
892:
893: ip_lock(port);
894: assert(ip_active(port));
895:
896: name = port->ip_receiver_name;
897: assert(name != MACH_PORT_NULL);
898: ip_pset = port->ip_pset;
899:
900: ip_unlock(port);
901:
902: if (pset == ip_pset) {
903: ipc_entry_num_t actual = *actualp;
904:
905: if (actual < maxnames)
906: names[actual] = name;
907:
908: *actualp = actual+1;
909: }
910: }
911:
912: /*
913: * Routine: mach_port_get_set_status [kernel call]
914: * Purpose:
915: * Retrieves a list of members in a port set.
916: * Returns the space's name for each receive right member.
917: * Conditions:
918: * Nothing locked.
919: * Returns:
920: * KERN_SUCCESS Retrieved list of members.
921: * KERN_INVALID_TASK The space is null.
922: * KERN_INVALID_TASK The space is dead.
923: * KERN_INVALID_NAME The name doesn't denote a right.
924: * KERN_INVALID_RIGHT Name doesn't denote a port set.
925: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
926: */
927:
928: kern_return_t
929: mach_port_get_set_status(
930: ipc_space_t space,
931: mach_port_t name,
932: mach_port_t **members,
933: mach_msg_type_number_t *membersCnt)
934: {
935: ipc_entry_num_t actual; /* this many members */
936: ipc_entry_num_t maxnames; /* space for this many members */
937: kern_return_t kr;
938:
939: vm_size_t size; /* size of allocated memory */
940: vm_offset_t addr; /* allocated memory */
941: vm_map_copy_t memory; /* copied-in memory */
942:
943: if (space == IS_NULL)
944: return KERN_INVALID_TASK;
945:
946: size = PAGE_SIZE; /* initial guess */
947:
948: for (;;) {
949: ipc_tree_entry_t tentry;
950: ipc_entry_t entry, table;
951: ipc_entry_num_t tsize;
952: mach_port_index_t index;
953: mach_port_t *names;
954: ipc_pset_t pset;
955:
956: kr = vm_allocate(ipc_kernel_map, &addr, size, TRUE);
1.1.1.3 root 957: if (kr != KERN_SUCCESS) {
958: printf_once("no more room in ipc_kernel_map\n");
1.1 root 959: return KERN_RESOURCE_SHORTAGE;
1.1.1.3 root 960: }
1.1 root 961:
962: /* can't fault while we hold locks */
963:
964: kr = vm_map_pageable(ipc_kernel_map, addr, addr + size,
965: VM_PROT_READ|VM_PROT_WRITE);
966: assert(kr == KERN_SUCCESS);
967:
968: kr = ipc_right_lookup_read(space, name, &entry);
969: if (kr != KERN_SUCCESS) {
970: kmem_free(ipc_kernel_map, addr, size);
971: return kr;
972: }
973: /* space is read-locked and active */
974:
975: if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_PORT_SET) {
976: is_read_unlock(space);
977: kmem_free(ipc_kernel_map, addr, size);
978: return KERN_INVALID_RIGHT;
979: }
980:
981: pset = (ipc_pset_t) entry->ie_object;
982: assert(pset != IPS_NULL);
983: /* the port set must be active */
984:
985: names = (mach_port_t *) addr;
986: maxnames = size / sizeof(mach_port_t);
987: actual = 0;
988:
989: table = space->is_table;
990: tsize = space->is_table_size;
991:
992: for (index = 0; index < tsize; index++) {
993: ipc_entry_t ientry = &table[index];
994: ipc_entry_bits_t bits = ientry->ie_bits;
995:
996: if (bits & MACH_PORT_TYPE_RECEIVE) {
997: ipc_port_t port =
998: (ipc_port_t) ientry->ie_object;
999:
1000: mach_port_gst_helper(pset, port, maxnames,
1001: names, &actual);
1002: }
1003: }
1004:
1005: for (tentry = ipc_splay_traverse_start(&space->is_tree);
1006: tentry != ITE_NULL;
1007: tentry = ipc_splay_traverse_next(&space->is_tree,FALSE)) {
1008: ipc_entry_bits_t bits = tentry->ite_bits;
1009:
1010: assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE);
1011:
1012: if (bits & MACH_PORT_TYPE_RECEIVE) {
1013: ipc_port_t port =
1014: (ipc_port_t) tentry->ite_object;
1015:
1016: mach_port_gst_helper(pset, port, maxnames,
1017: names, &actual);
1018: }
1019: }
1020: ipc_splay_traverse_finish(&space->is_tree);
1021: is_read_unlock(space);
1022:
1023: if (actual <= maxnames)
1024: break;
1025:
1026: /* didn't have enough memory; allocate more */
1027:
1028: kmem_free(ipc_kernel_map, addr, size);
1029: size = round_page(actual * sizeof(mach_port_t)) + PAGE_SIZE;
1030: }
1031:
1032: if (actual == 0) {
1033: memory = VM_MAP_COPY_NULL;
1034:
1035: kmem_free(ipc_kernel_map, addr, size);
1036: } else {
1037: vm_size_t size_used;
1038:
1039: size_used = round_page(actual * sizeof(mach_port_t));
1040:
1041: /*
1042: * Make used memory pageable and get it into
1043: * copied-in form. Free any unused memory.
1044: */
1045:
1046: kr = vm_map_pageable(ipc_kernel_map,
1047: addr, addr + size_used,
1048: VM_PROT_NONE);
1049: assert(kr == KERN_SUCCESS);
1050:
1051: kr = vm_map_copyin(ipc_kernel_map, addr, size_used,
1052: TRUE, &memory);
1053: assert(kr == KERN_SUCCESS);
1054:
1055: if (size_used != size)
1056: kmem_free(ipc_kernel_map,
1057: addr + size_used, size - size_used);
1058: }
1059:
1060: *members = (mach_port_t *) memory;
1061: *membersCnt = actual;
1062: return KERN_SUCCESS;
1063: }
1064:
1065: /*
1066: * Routine: mach_port_move_member [kernel call]
1067: * Purpose:
1068: * If after is MACH_PORT_NULL, removes member
1069: * from the port set it is in. Otherwise, adds
1070: * member to after, removing it from any set
1071: * it might already be in.
1072: * Conditions:
1073: * Nothing locked.
1074: * Returns:
1075: * KERN_SUCCESS Moved the port.
1076: * KERN_INVALID_TASK The space is null.
1077: * KERN_INVALID_TASK The space is dead.
1078: * KERN_INVALID_NAME Member didn't denote a right.
1079: * KERN_INVALID_RIGHT Member didn't denote a receive right.
1080: * KERN_INVALID_NAME After didn't denote a right.
1081: * KERN_INVALID_RIGHT After didn't denote a port set right.
1082: * KERN_NOT_IN_SET
1083: * After is MACH_PORT_NULL and Member isn't in a port set.
1084: */
1085:
1086: kern_return_t
1087: mach_port_move_member(
1088: ipc_space_t space,
1089: mach_port_t member,
1090: mach_port_t after)
1091: {
1092: ipc_entry_t entry;
1093: ipc_port_t port;
1094: ipc_pset_t nset;
1095: kern_return_t kr;
1096:
1097: if (space == IS_NULL)
1098: return KERN_INVALID_TASK;
1099:
1100: kr = ipc_right_lookup_read(space, member, &entry);
1101: if (kr != KERN_SUCCESS)
1102: return kr;
1103: /* space is read-locked and active */
1104:
1105: if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) {
1106: is_read_unlock(space);
1107: return KERN_INVALID_RIGHT;
1108: }
1109:
1110: port = (ipc_port_t) entry->ie_object;
1111: assert(port != IP_NULL);
1112:
1113: if (after == MACH_PORT_NULL)
1114: nset = IPS_NULL;
1115: else {
1116: entry = ipc_entry_lookup(space, after);
1117: if (entry == IE_NULL) {
1118: is_read_unlock(space);
1119: return KERN_INVALID_NAME;
1120: }
1121:
1122: if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) {
1123: is_read_unlock(space);
1124: return KERN_INVALID_RIGHT;
1125: }
1126:
1127: nset = (ipc_pset_t) entry->ie_object;
1128: assert(nset != IPS_NULL);
1129: }
1130:
1131: kr = ipc_pset_move(space, port, nset);
1132: /* space is unlocked */
1133: return kr;
1134: }
1135:
1136: /*
1137: * Routine: mach_port_request_notification [kernel call]
1138: * Purpose:
1139: * Requests a notification. The caller supplies
1140: * a send-once right for the notification to use,
1141: * and the call returns the previously registered
1142: * send-once right, if any. Possible types:
1143: *
1144: * MACH_NOTIFY_PORT_DESTROYED
1145: * Requests a port-destroyed notification
1146: * for a receive right. Sync should be zero.
1147: * MACH_NOTIFY_NO_SENDERS
1148: * Requests a no-senders notification for a
1149: * receive right. If there are currently no
1150: * senders, sync is less than or equal to the
1151: * current make-send count, and a send-once right
1152: * is supplied, then an immediate no-senders
1153: * notification is generated.
1154: * MACH_NOTIFY_DEAD_NAME
1155: * Requests a dead-name notification for a send
1156: * or receive right. If the name is already a
1157: * dead name, sync is non-zero, and a send-once
1158: * right is supplied, then an immediate dead-name
1159: * notification is generated.
1160: * Conditions:
1161: * Nothing locked.
1162: * Returns:
1163: * KERN_SUCCESS Requested a notification.
1164: * KERN_INVALID_TASK The space is null.
1165: * KERN_INVALID_TASK The space is dead.
1166: * KERN_INVALID_VALUE Bad id value.
1167: * KERN_INVALID_NAME Name doesn't denote a right.
1168: * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1169: * KERN_INVALID_CAPABILITY The notify port is dead.
1170: * MACH_NOTIFY_PORT_DESTROYED:
1171: * KERN_INVALID_VALUE Sync isn't zero.
1172: * MACH_NOTIFY_DEAD_NAME:
1173: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1174: * KERN_INVALID_ARGUMENT Name denotes dead name, but
1175: * sync is zero or notify is IP_NULL.
1176: * KERN_UREFS_OVERFLOW Name denotes dead name, but
1177: * generating immediate notif. would overflow urefs.
1178: */
1179:
1180: kern_return_t
1181: mach_port_request_notification(
1182: ipc_space_t space,
1183: mach_port_t name,
1184: mach_msg_id_t id,
1185: mach_port_mscount_t sync,
1186: ipc_port_t notify,
1187: ipc_port_t *previousp)
1188: {
1189: kern_return_t kr;
1190:
1191: if (space == IS_NULL)
1192: return KERN_INVALID_TASK;
1193:
1194: if (notify == IP_DEAD)
1195: return KERN_INVALID_CAPABILITY;
1196:
1197: switch (id) {
1198: case MACH_NOTIFY_PORT_DESTROYED: {
1199: ipc_port_t port, previous;
1200:
1201: if (sync != 0)
1202: return KERN_INVALID_VALUE;
1203:
1204: kr = ipc_port_translate_receive(space, name, &port);
1205: if (kr != KERN_SUCCESS)
1206: return kr;
1207: /* port is locked and active */
1208:
1209: ipc_port_pdrequest(port, notify, &previous);
1210: /* port is unlocked */
1211:
1212: *previousp = previous;
1213: break;
1214: }
1215:
1216: case MACH_NOTIFY_NO_SENDERS: {
1217: ipc_port_t port;
1218:
1219: kr = ipc_port_translate_receive(space, name, &port);
1220: if (kr != KERN_SUCCESS)
1221: return kr;
1222: /* port is locked and active */
1223:
1224: ipc_port_nsrequest(port, sync, notify, previousp);
1225: /* port is unlocked */
1226: break;
1227: }
1228:
1229: case MACH_NOTIFY_DEAD_NAME:
1230: kr = ipc_right_dnrequest(space, name, sync != 0,
1231: notify, previousp);
1232: if (kr != KERN_SUCCESS)
1233: return kr;
1234: break;
1235:
1236: default:
1237: return KERN_INVALID_VALUE;
1238: }
1239:
1240: return KERN_SUCCESS;
1241: }
1242:
1243: /*
1244: * Routine: mach_port_insert_right [kernel call]
1245: * Purpose:
1246: * Inserts a right into a space, as if the space
1247: * voluntarily received the right in a message,
1248: * except that the right gets the specified name.
1249: * Conditions:
1250: * Nothing locked.
1251: * Returns:
1252: * KERN_SUCCESS Inserted the right.
1253: * KERN_INVALID_TASK The space is null.
1254: * KERN_INVALID_TASK The space is dead.
1255: * KERN_INVALID_VALUE The name isn't a legal name.
1256: * KERN_NAME_EXISTS The name already denotes a right.
1257: * KERN_INVALID_VALUE Message doesn't carry a port right.
1258: * KERN_INVALID_CAPABILITY Port is null or dead.
1259: * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1260: * KERN_RIGHT_EXISTS Space has rights under another name.
1261: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1262: */
1263:
1264: kern_return_t
1265: mach_port_insert_right(
1266: ipc_space_t space,
1267: mach_port_t name,
1268: ipc_port_t poly,
1269: mach_msg_type_name_t polyPoly)
1270: {
1271: if (space == IS_NULL)
1272: return KERN_INVALID_TASK;
1273:
1274: if (!MACH_PORT_VALID(name) ||
1275: !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly))
1276: return KERN_INVALID_VALUE;
1277:
1.1.1.3 root 1278: if (!IO_VALID((ipc_object_t)poly))
1.1 root 1279: return KERN_INVALID_CAPABILITY;
1280:
1.1.1.3 root 1281: return ipc_object_copyout_name(space, (ipc_object_t)poly,
1282: polyPoly, FALSE, name);
1.1 root 1283: }
1284:
1285: /*
1286: * Routine: mach_port_extract_right [kernel call]
1287: * Purpose:
1288: * Extracts a right from a space, as if the space
1289: * voluntarily sent the right to the caller.
1290: * Conditions:
1291: * Nothing locked.
1292: * Returns:
1293: * KERN_SUCCESS Extracted the right.
1294: * KERN_INVALID_TASK The space is null.
1295: * KERN_INVALID_TASK The space is dead.
1296: * KERN_INVALID_VALUE Requested type isn't a port right.
1297: * KERN_INVALID_NAME Name doesn't denote a right.
1298: * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1299: */
1300:
1301: kern_return_t
1302: mach_port_extract_right(
1303: ipc_space_t space,
1304: mach_port_t name,
1305: mach_msg_type_name_t msgt_name,
1306: ipc_port_t *poly,
1307: mach_msg_type_name_t *polyPoly)
1308: {
1309: kern_return_t kr;
1310:
1311: if (space == IS_NULL)
1312: return KERN_INVALID_TASK;
1313:
1314: if (!MACH_MSG_TYPE_PORT_ANY(msgt_name))
1315: return KERN_INVALID_VALUE;
1316:
1317: kr = ipc_object_copyin(space, name, msgt_name, (ipc_object_t *) poly);
1318:
1319: if (kr == KERN_SUCCESS)
1320: *polyPoly = ipc_object_copyin_type(msgt_name);
1321: return kr;
1322: }
1323:
1324: /*
1325: * Routine: mach_port_get_receive_status [kernel call]
1326: * Purpose:
1327: * Retrieves mucho info about a receive right.
1328: * Conditions:
1329: * Nothing locked.
1330: * Returns:
1331: * KERN_SUCCESS Retrieved status.
1332: * KERN_INVALID_TASK The space is null.
1333: * KERN_INVALID_TASK The space is dead.
1334: * KERN_INVALID_NAME The name doesn't denote a right.
1335: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1336: */
1337:
1338: kern_return_t
1.1.1.4 ! root 1339: mach_port_get_receive_status(
! 1340: ipc_space_t space,
! 1341: mach_port_t name,
! 1342: mach_port_status_t *statusp)
1.1 root 1343: {
1344: ipc_port_t port;
1345: kern_return_t kr;
1346:
1347: if (space == IS_NULL)
1348: return KERN_INVALID_TASK;
1349:
1350: kr = ipc_port_translate_receive(space, name, &port);
1351: if (kr != KERN_SUCCESS)
1352: return kr;
1353: /* port is locked and active */
1354:
1355: if (port->ip_pset != IPS_NULL) {
1356: ipc_pset_t pset = port->ip_pset;
1357:
1358: ips_lock(pset);
1359: if (!ips_active(pset)) {
1360: ipc_pset_remove(pset, port);
1361: ips_check_unlock(pset);
1362: goto no_port_set;
1363: } else {
1364: statusp->mps_pset = pset->ips_local_name;
1365: imq_lock(&pset->ips_messages);
1366: statusp->mps_seqno = port->ip_seqno;
1367: imq_unlock(&pset->ips_messages);
1368: ips_unlock(pset);
1369: assert(MACH_PORT_VALID(statusp->mps_pset));
1370: }
1371: } else {
1372: no_port_set:
1373: statusp->mps_pset = MACH_PORT_NULL;
1374: imq_lock(&port->ip_messages);
1375: statusp->mps_seqno = port->ip_seqno;
1376: imq_unlock(&port->ip_messages);
1377: }
1378:
1379: statusp->mps_mscount = port->ip_mscount;
1380: statusp->mps_qlimit = port->ip_qlimit;
1381: statusp->mps_msgcount = port->ip_msgcount;
1382: statusp->mps_sorights = port->ip_sorights;
1383: statusp->mps_srights = port->ip_srights > 0;
1384: statusp->mps_pdrequest = port->ip_pdrequest != IP_NULL;
1385: statusp->mps_nsrequest = port->ip_nsrequest != IP_NULL;
1386: ip_unlock(port);
1387:
1388: return KERN_SUCCESS;
1389: }
1390:
1391: #ifdef MIGRATING_THREADS
1392: kern_return_t
1.1.1.4 ! root 1393: mach_port_set_rpcinfo(
! 1394: ipc_space_t space,
! 1395: mach_port_t name,
! 1396: void *rpc_info,
! 1397: unsigned int rpc_info_count)
1.1 root 1398: {
1399: ipc_target_t target;
1400: ipc_object_t object;
1401: kern_return_t kr;
1402:
1403: if (space == IS_NULL)
1404: return KERN_INVALID_TASK;
1405:
1406: kr = ipc_object_translate(space, name,
1407: MACH_PORT_RIGHT_PORT_SET, &object);
1408: if (kr == KERN_SUCCESS)
1409: target = &((ipc_pset_t)object)->ips_target;
1410: else {
1411: kr = ipc_object_translate(space, name,
1412: MACH_PORT_RIGHT_RECEIVE, &object);
1413: if (kr != KERN_SUCCESS)
1414: return kr;
1415: target = &((ipc_port_t)object)->ip_target;
1416: }
1417:
1418: /* port/pset is locked and active */
1419:
1420: kr = port_machine_set_rpcinfo(target, rpc_info, rpc_info_count);
1421:
1422: io_unlock(object);
1423:
1424: return kr;
1425: }
1426:
1427: #if 1
1428: int sacts, maxsacts;
1429: #endif
1430:
1.1.1.4 ! root 1431: void sact_count(void)
1.1 root 1432: {
1433: printf("%d server activations in use, %d max\n", sacts, maxsacts);
1434: }
1435:
1436: kern_return_t
1.1.1.4 ! root 1437: mach_port_create_act(
! 1438: task_t task,
! 1439: mach_port_t name,
! 1440: vm_offset_t user_stack,
! 1441: vm_offset_t user_rbuf,
! 1442: vm_size_t user_rbuf_size,
! 1443: Act **out_act)
1.1 root 1444: {
1445: ipc_target_t target;
1446: ipc_space_t space;
1447: ipc_object_t object;
1448: kern_return_t kr;
1449: Act *act;
1450:
1451: if (task == 0)
1452: return KERN_INVALID_TASK;
1453:
1454: /* First create the new activation. */
1455: kr = act_create(task, user_stack, user_rbuf, user_rbuf_size, &act);
1456: if (kr != KERN_SUCCESS)
1457: return kr;
1458:
1459: space = task->itk_space;
1460:
1461: kr = ipc_object_translate(space, name,
1462: MACH_PORT_RIGHT_PORT_SET, &object);
1463: if (kr == KERN_SUCCESS)
1464: target = &((ipc_pset_t)object)->ips_target;
1465: else {
1466: kr = ipc_object_translate(space, name,
1467: MACH_PORT_RIGHT_RECEIVE, &object);
1468: if (kr != KERN_SUCCESS) {
1469: act_terminate(act);
1470: act_deallocate(act);
1471: return kr;
1472: }
1473: target = &((ipc_port_t)object)->ip_target;
1474: }
1475:
1476: /* port/pset is locked and active */
1477: #if 0
1478: printf("act port/pset %08x ipc_target %08x stack %08x act %08x\n",
1479: object, target, user_stack, act);
1480: #endif
1481:
1482: /* Assign the activation to the port's actpool. */
1483: kr = act_set_target(act, target);
1484: if (kr != KERN_SUCCESS) {
1485: io_unlock(object);
1486: act_terminate(act);
1487: act_deallocate(act);
1488: return kr;
1489: }
1490: #if 0
1491: printf(" actpool %08x act %08x\n", target->ip_actpool, act);
1492: #endif
1493:
1494: io_unlock(object);
1495:
1496: /* Pass our reference to the activation back to the user. */
1497: *out_act = act;
1498:
1499: #if 1
1500: sacts++;
1501: if (sacts > maxsacts)
1502: maxsacts = sacts;
1503: act->mact.pcb->ss.mpsfu_high = 0x69;
1504: #endif
1505: return KERN_SUCCESS;
1506: }
1507:
1508: #ifdef RPCKERNELSIG
1509: kern_return_t
1.1.1.4 ! root 1510: mach_port_set_syscall_right(
! 1511: task_t task,
! 1512: mach_port_t name)
1.1 root 1513: {
1514: ipc_entry_t entry;
1515: kern_return_t kr;
1516:
1517: if (task == IS_NULL)
1518: return KERN_INVALID_TASK;
1519:
1520: kr = ipc_right_lookup_write(task, name, &entry);
1521: if (kr != KERN_SUCCESS) {
1522: return kr;
1523: }
1524:
1525: if (!(entry->ie_bits & MACH_PORT_TYPE(MACH_PORT_RIGHT_SEND))) {
1526: is_write_unlock(space);
1527: return KERN_INVALID_RIGHT;
1528: }
1529:
1530: task->syscall_ipc_entry = *entry;
1531:
1532: is_write_unlock(space);
1533:
1534: return KERN_SUCCESS;
1535: }
1536: #endif
1537: #endif /* MIGRATING_THREADS */
1.1.1.4 ! root 1538:
! 1539: /*
! 1540: * Routine: mach_port_set_protected_payload [kernel call]
! 1541: * Purpose:
! 1542: * Changes a receive right's protected payload.
! 1543: * Conditions:
! 1544: * Nothing locked.
! 1545: * Returns:
! 1546: * KERN_SUCCESS Set protected payload.
! 1547: * KERN_INVALID_TASK The space is null.
! 1548: * KERN_INVALID_TASK The space is dead.
! 1549: * KERN_INVALID_NAME The name doesn't denote a right.
! 1550: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
! 1551: */
! 1552:
! 1553: kern_return_t
! 1554: mach_port_set_protected_payload(
! 1555: ipc_space_t space,
! 1556: mach_port_t name,
! 1557: unsigned long payload)
! 1558: {
! 1559: ipc_port_t port;
! 1560: kern_return_t kr;
! 1561:
! 1562: if (space == IS_NULL)
! 1563: return KERN_INVALID_TASK;
! 1564:
! 1565: kr = ipc_port_translate_receive(space, name, &port);
! 1566: if (kr != KERN_SUCCESS)
! 1567: return kr;
! 1568: /* port is locked and active */
! 1569:
! 1570: ipc_port_set_protected_payload(port, payload);
! 1571:
! 1572: ip_unlock(port);
! 1573: return KERN_SUCCESS;
! 1574: }
! 1575:
! 1576: /*
! 1577: * Routine: mach_port_clear_protected_payload [kernel call]
! 1578: * Purpose:
! 1579: * Clears a receive right's protected payload.
! 1580: * Conditions:
! 1581: * Nothing locked.
! 1582: * Returns:
! 1583: * KERN_SUCCESS Clear protected payload.
! 1584: * KERN_INVALID_TASK The space is null.
! 1585: * KERN_INVALID_TASK The space is dead.
! 1586: * KERN_INVALID_NAME The name doesn't denote a right.
! 1587: * KERN_INVALID_RIGHT Name doesn't denote receive rights.
! 1588: */
! 1589:
! 1590: kern_return_t
! 1591: mach_port_clear_protected_payload(
! 1592: ipc_space_t space,
! 1593: mach_port_t name)
! 1594: {
! 1595: ipc_port_t port;
! 1596: kern_return_t kr;
! 1597:
! 1598: if (space == IS_NULL)
! 1599: return KERN_INVALID_TASK;
! 1600:
! 1601: kr = ipc_port_translate_receive(space, name, &port);
! 1602: if (kr != KERN_SUCCESS)
! 1603: return kr;
! 1604: /* port is locked and active */
! 1605:
! 1606: ipc_port_clear_protected_payload(port);
! 1607:
! 1608: ip_unlock(port);
! 1609: return KERN_SUCCESS;
! 1610: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.