|
|
1.1.1.2 root 1: /*
1.1 root 2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
4: * All Rights Reserved.
1.1.1.2 root 5: *
1.1 root 6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
1.1.1.2 root 11: *
1.1 root 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.2 root 15: *
1.1 root 16: * Carnegie Mellon requests users of this software to return to
1.1.1.2 root 17: *
1.1 root 18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
1.1.1.2 root 22: *
1.1 root 23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * File: ipc_tt.c
28: * Purpose:
29: * Task and thread related IPC functions.
30: */
31:
32: #include <mach/boolean.h>
33: #include <mach/kern_return.h>
34: #include <mach/mach_param.h>
35: #include <mach/task_special_ports.h>
36: #include <mach/thread_special_ports.h>
37: #include <vm/vm_kern.h>
1.1.1.4 ! root 38: #include <kern/debug.h>
! 39: #include <kern/kalloc.h>
1.1 root 40: #include <kern/task.h>
41: #include <kern/thread.h>
42: #include <kern/ipc_kobject.h>
43: #include <kern/ipc_tt.h>
44: #include <ipc/ipc_space.h>
45: #include <ipc/ipc_table.h>
46: #include <ipc/ipc_port.h>
47: #include <ipc/ipc_right.h>
48: #include <ipc/ipc_entry.h>
49: #include <ipc/ipc_object.h>
50:
51:
52:
53: /*
54: * Routine: ipc_task_init
55: * Purpose:
56: * Initialize a task's IPC state.
57: *
58: * If non-null, some state will be inherited from the parent.
59: * The parent must be appropriately initialized.
60: * Conditions:
61: * Nothing locked.
62: */
63:
64: void
65: ipc_task_init(
66: task_t task,
67: task_t parent)
68: {
69: ipc_space_t space;
70: ipc_port_t kport;
71: kern_return_t kr;
72: int i;
73:
74:
75: kr = ipc_space_create(&ipc_table_entries[0], &space);
76: if (kr != KERN_SUCCESS)
77: panic("ipc_task_init");
78:
79:
80: kport = ipc_port_alloc_kernel();
81: if (kport == IP_NULL)
82: panic("ipc_task_init");
83:
84: itk_lock_init(task);
85: task->itk_self = kport;
86: task->itk_sself = ipc_port_make_send(kport);
87: task->itk_space = space;
88:
89: if (parent == TASK_NULL) {
90: task->itk_exception = IP_NULL;
91: task->itk_bootstrap = IP_NULL;
92: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
93: task->itk_registered[i] = IP_NULL;
94: } else {
95: itk_lock(parent);
96: assert(parent->itk_self != IP_NULL);
97:
98: /* inherit registered ports */
99:
100: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
101: task->itk_registered[i] =
102: ipc_port_copy_send(parent->itk_registered[i]);
103:
104: /* inherit exception and bootstrap ports */
105:
106: task->itk_exception =
107: ipc_port_copy_send(parent->itk_exception);
108: task->itk_bootstrap =
109: ipc_port_copy_send(parent->itk_bootstrap);
110:
111: itk_unlock(parent);
112: }
113: }
114:
115: /*
116: * Routine: ipc_task_enable
117: * Purpose:
118: * Enable a task for IPC access.
119: * Conditions:
120: * Nothing locked.
121: */
122:
123: void
124: ipc_task_enable(
125: task_t task)
126: {
127: ipc_port_t kport;
128:
129: itk_lock(task);
130: kport = task->itk_self;
131: if (kport != IP_NULL)
132: ipc_kobject_set(kport, (ipc_kobject_t) task, IKOT_TASK);
133: itk_unlock(task);
134: }
135:
136: /*
137: * Routine: ipc_task_disable
138: * Purpose:
139: * Disable IPC access to a task.
140: * Conditions:
141: * Nothing locked.
142: */
143:
144: void
145: ipc_task_disable(
146: task_t task)
147: {
148: ipc_port_t kport;
149:
150: itk_lock(task);
151: kport = task->itk_self;
152: if (kport != IP_NULL)
153: ipc_kobject_set(kport, IKO_NULL, IKOT_NONE);
154: itk_unlock(task);
155: }
156:
157: /*
158: * Routine: ipc_task_terminate
159: * Purpose:
160: * Clean up and destroy a task's IPC state.
161: * Conditions:
162: * Nothing locked. The task must be suspended.
163: * (Or the current thread must be in the task.)
164: */
165:
166: void
167: ipc_task_terminate(
168: task_t task)
169: {
170: ipc_port_t kport;
171: int i;
172:
173: itk_lock(task);
174: kport = task->itk_self;
175:
176: if (kport == IP_NULL) {
177: /* the task is already terminated (can this happen?) */
178: itk_unlock(task);
179: return;
180: }
181:
182: task->itk_self = IP_NULL;
183: itk_unlock(task);
184:
185: /* release the naked send rights */
186:
187: if (IP_VALID(task->itk_sself))
188: ipc_port_release_send(task->itk_sself);
189: if (IP_VALID(task->itk_exception))
190: ipc_port_release_send(task->itk_exception);
191: if (IP_VALID(task->itk_bootstrap))
192: ipc_port_release_send(task->itk_bootstrap);
193:
194: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
195: if (IP_VALID(task->itk_registered[i]))
196: ipc_port_release_send(task->itk_registered[i]);
197:
198: /* destroy the space, leaving just a reference for it */
199:
200: ipc_space_destroy(task->itk_space);
201:
202: /* destroy the kernel port */
203:
204: ipc_port_dealloc_kernel(kport);
205: }
206:
207: /*
208: * Routine: ipc_thread_init
209: * Purpose:
210: * Initialize a thread's IPC state.
211: * Conditions:
212: * Nothing locked.
213: */
214:
215: void
216: ipc_thread_init(thread)
217: thread_t thread;
218: {
219: ipc_port_t kport;
220:
221: kport = ipc_port_alloc_kernel();
222: if (kport == IP_NULL)
223: panic("ipc_thread_init");
224:
225: ipc_thread_links_init(thread);
226: ipc_kmsg_queue_init(&thread->ith_messages);
227:
228: ith_lock_init(thread);
229: thread->ith_self = kport;
230: thread->ith_sself = ipc_port_make_send(kport);
231: thread->ith_exception = IP_NULL;
232:
233: thread->ith_mig_reply = MACH_PORT_NULL;
234: thread->ith_rpc_reply = IP_NULL;
235: }
236:
237: /*
238: * Routine: ipc_thread_enable
239: * Purpose:
240: * Enable a thread for IPC access.
241: * Conditions:
242: * Nothing locked.
243: */
244:
245: void
246: ipc_thread_enable(thread)
247: thread_t thread;
248: {
249: ipc_port_t kport;
250:
251: ith_lock(thread);
252: kport = thread->ith_self;
253: if (kport != IP_NULL)
254: ipc_kobject_set(kport, (ipc_kobject_t) thread, IKOT_THREAD);
255: ith_unlock(thread);
256: }
257:
258: /*
259: * Routine: ipc_thread_disable
260: * Purpose:
261: * Disable IPC access to a thread.
262: * Conditions:
263: * Nothing locked.
264: */
265:
266: void
267: ipc_thread_disable(thread)
268: thread_t thread;
269: {
270: ipc_port_t kport;
271:
272: ith_lock(thread);
273: kport = thread->ith_self;
274: if (kport != IP_NULL)
275: ipc_kobject_set(kport, IKO_NULL, IKOT_NONE);
276: ith_unlock(thread);
277: }
278:
279: /*
280: * Routine: ipc_thread_terminate
281: * Purpose:
282: * Clean up and destroy a thread's IPC state.
283: * Conditions:
284: * Nothing locked. The thread must be suspended.
285: * (Or be the current thread.)
286: */
287:
288: void
289: ipc_thread_terminate(thread)
290: thread_t thread;
291: {
292: ipc_port_t kport;
293:
294: ith_lock(thread);
295: kport = thread->ith_self;
296:
297: if (kport == IP_NULL) {
298: /* the thread is already terminated (can this happen?) */
299: ith_unlock(thread);
300: return;
301: }
302:
303: thread->ith_self = IP_NULL;
304: ith_unlock(thread);
305:
306: assert(ipc_kmsg_queue_empty(&thread->ith_messages));
307:
308: /* release the naked send rights */
309:
310: if (IP_VALID(thread->ith_sself))
311: ipc_port_release_send(thread->ith_sself);
312: if (IP_VALID(thread->ith_exception))
313: ipc_port_release_send(thread->ith_exception);
314:
315: /* destroy the kernel port */
316:
317: ipc_port_dealloc_kernel(kport);
318: }
319:
320: #if 0
321: /*
322: * Routine: retrieve_task_self
323: * Purpose:
324: * Return a send right (possibly null/dead)
325: * for the task's user-visible self port.
326: * Conditions:
327: * Nothing locked.
328: */
329:
330: ipc_port_t
331: retrieve_task_self(task)
332: task_t task;
333: {
334: ipc_port_t port;
335:
336: assert(task != TASK_NULL);
337:
338: itk_lock(task);
339: if (task->itk_self != IP_NULL)
340: port = ipc_port_copy_send(task->itk_sself);
341: else
342: port = IP_NULL;
343: itk_unlock(task);
344:
345: return port;
346: }
347:
348: /*
349: * Routine: retrieve_thread_self
350: * Purpose:
351: * Return a send right (possibly null/dead)
352: * for the thread's user-visible self port.
353: * Conditions:
354: * Nothing locked.
355: */
356:
357: ipc_port_t
358: retrieve_thread_self(thread)
359: thread_t thread;
360: {
361: ipc_port_t port;
362:
363: assert(thread != ITH_NULL);
364:
365: ith_lock(thread);
366: if (thread->ith_self != IP_NULL)
367: port = ipc_port_copy_send(thread->ith_sself);
368: else
369: port = IP_NULL;
370: ith_unlock(thread);
371:
372: return port;
373: }
1.1.1.3 root 374: #endif /* 0 */
1.1 root 375:
376: /*
377: * Routine: retrieve_task_self_fast
378: * Purpose:
379: * Optimized version of retrieve_task_self,
380: * that only works for the current task.
381: *
382: * Return a send right (possibly null/dead)
383: * for the task's user-visible self port.
384: * Conditions:
385: * Nothing locked.
386: */
387:
388: ipc_port_t
389: retrieve_task_self_fast(
390: register task_t task)
391: {
392: register ipc_port_t port;
393:
394: assert(task == current_task());
395:
396: itk_lock(task);
397: assert(task->itk_self != IP_NULL);
398:
399: if ((port = task->itk_sself) == task->itk_self) {
400: /* no interposing */
401:
402: ip_lock(port);
403: assert(ip_active(port));
404: ip_reference(port);
405: port->ip_srights++;
406: ip_unlock(port);
407: } else
408: port = ipc_port_copy_send(port);
409: itk_unlock(task);
410:
411: return port;
412: }
413:
414: /*
415: * Routine: retrieve_thread_self_fast
416: * Purpose:
417: * Optimized version of retrieve_thread_self,
418: * that only works for the current thread.
419: *
420: * Return a send right (possibly null/dead)
421: * for the thread's user-visible self port.
422: * Conditions:
423: * Nothing locked.
424: */
425:
426: ipc_port_t
427: retrieve_thread_self_fast(thread)
428: register thread_t thread;
429: {
430: register ipc_port_t port;
431:
432: assert(thread == current_thread());
433:
434: ith_lock(thread);
435: assert(thread->ith_self != IP_NULL);
436:
437: if ((port = thread->ith_sself) == thread->ith_self) {
438: /* no interposing */
439:
440: ip_lock(port);
441: assert(ip_active(port));
442: ip_reference(port);
443: port->ip_srights++;
444: ip_unlock(port);
445: } else
446: port = ipc_port_copy_send(port);
447: ith_unlock(thread);
448:
449: return port;
450: }
451:
452: #if 0
453: /*
454: * Routine: retrieve_task_exception
455: * Purpose:
456: * Return a send right (possibly null/dead)
457: * for the task's exception port.
458: * Conditions:
459: * Nothing locked.
460: */
461:
462: ipc_port_t
463: retrieve_task_exception(task)
464: task_t task;
465: {
466: ipc_port_t port;
467:
468: assert(task != TASK_NULL);
469:
470: itk_lock(task);
471: if (task->itk_self != IP_NULL)
472: port = ipc_port_copy_send(task->itk_exception);
473: else
474: port = IP_NULL;
475: itk_unlock(task);
476:
477: return port;
478: }
479:
480: /*
481: * Routine: retrieve_thread_exception
482: * Purpose:
483: * Return a send right (possibly null/dead)
484: * for the thread's exception port.
485: * Conditions:
486: * Nothing locked.
487: */
488:
489: ipc_port_t
490: retrieve_thread_exception(thread)
491: thread_t thread;
492: {
493: ipc_port_t port;
494:
495: assert(thread != ITH_NULL);
496:
497: ith_lock(thread);
498: if (thread->ith_self != IP_NULL)
499: port = ipc_port_copy_send(thread->ith_exception);
500: else
501: port = IP_NULL;
502: ith_unlock(thread);
503:
504: return port;
505: }
1.1.1.3 root 506: #endif /* 0 */
1.1 root 507:
508: /*
509: * Routine: mach_task_self [mach trap]
510: * Purpose:
511: * Give the caller send rights for his own task port.
512: * Conditions:
513: * Nothing locked.
514: * Returns:
515: * MACH_PORT_NULL if there are any resource failures
516: * or other errors.
517: */
518:
519: mach_port_t
520: mach_task_self(void)
521: {
522: task_t task = current_task();
523: ipc_port_t sright;
524:
525: sright = retrieve_task_self_fast(task);
526: return ipc_port_copyout_send(sright, task->itk_space);
527: }
528:
529: /*
530: * Routine: mach_thread_self [mach trap]
531: * Purpose:
532: * Give the caller send rights for his own thread port.
533: * Conditions:
534: * Nothing locked.
535: * Returns:
536: * MACH_PORT_NULL if there are any resource failures
537: * or other errors.
538: */
539:
540: mach_port_t
1.1.1.4 ! root 541: mach_thread_self(void)
1.1 root 542: {
543: thread_t thread = current_thread();
544: task_t task = thread->task;
545: ipc_port_t sright;
546:
547: sright = retrieve_thread_self_fast(thread);
548: return ipc_port_copyout_send(sright, task->itk_space);
549: }
550:
551: /*
552: * Routine: mach_reply_port [mach trap]
553: * Purpose:
554: * Allocate a port for the caller.
555: * Conditions:
556: * Nothing locked.
557: * Returns:
558: * MACH_PORT_NULL if there are any resource failures
559: * or other errors.
560: */
561:
562: mach_port_t
563: mach_reply_port(void)
564: {
565: ipc_port_t port;
566: mach_port_t name;
567: kern_return_t kr;
568:
569: kr = ipc_port_alloc(current_task()->itk_space, &name, &port);
570: if (kr == KERN_SUCCESS)
571: ip_unlock(port);
572: else
573: name = MACH_PORT_NULL;
574:
575: return name;
576: }
577:
578: /*
579: * Routine: task_get_special_port [kernel call]
580: * Purpose:
581: * Clones a send right for one of the task's
582: * special ports.
583: * Conditions:
584: * Nothing locked.
585: * Returns:
586: * KERN_SUCCESS Extracted a send right.
587: * KERN_INVALID_ARGUMENT The task is null.
588: * KERN_FAILURE The task/space is dead.
589: * KERN_INVALID_ARGUMENT Invalid special port.
590: */
591:
592: kern_return_t
593: task_get_special_port(
594: task_t task,
595: int which,
596: ipc_port_t *portp)
597: {
598: ipc_port_t *whichp;
599: ipc_port_t port;
600:
601: if (task == TASK_NULL)
602: return KERN_INVALID_ARGUMENT;
603:
604: switch (which) {
605: case TASK_KERNEL_PORT:
606: whichp = &task->itk_sself;
607: break;
608:
609: case TASK_EXCEPTION_PORT:
610: whichp = &task->itk_exception;
611: break;
612:
613: case TASK_BOOTSTRAP_PORT:
614: whichp = &task->itk_bootstrap;
615: break;
616:
617: default:
618: return KERN_INVALID_ARGUMENT;
619: }
620:
621: itk_lock(task);
622: if (task->itk_self == IP_NULL) {
623: itk_unlock(task);
624: return KERN_FAILURE;
625: }
626:
627: port = ipc_port_copy_send(*whichp);
628: itk_unlock(task);
629:
630: *portp = port;
631: return KERN_SUCCESS;
632: }
633:
634: /*
635: * Routine: task_set_special_port [kernel call]
636: * Purpose:
637: * Changes one of the task's special ports,
638: * setting it to the supplied send right.
639: * Conditions:
640: * Nothing locked. If successful, consumes
641: * the supplied send right.
642: * Returns:
643: * KERN_SUCCESS Changed the special port.
644: * KERN_INVALID_ARGUMENT The task is null.
645: * KERN_FAILURE The task/space is dead.
646: * KERN_INVALID_ARGUMENT Invalid special port.
647: */
648:
649: kern_return_t
650: task_set_special_port(
651: task_t task,
652: int which,
653: ipc_port_t port)
654: {
655: ipc_port_t *whichp;
656: ipc_port_t old;
657:
658: if (task == TASK_NULL)
659: return KERN_INVALID_ARGUMENT;
660:
661: switch (which) {
662: case TASK_KERNEL_PORT:
663: whichp = &task->itk_sself;
664: break;
665:
666: case TASK_EXCEPTION_PORT:
667: whichp = &task->itk_exception;
668: break;
669:
670: case TASK_BOOTSTRAP_PORT:
671: whichp = &task->itk_bootstrap;
672: break;
673:
674: default:
675: return KERN_INVALID_ARGUMENT;
676: }
677:
678: itk_lock(task);
679: if (task->itk_self == IP_NULL) {
680: itk_unlock(task);
681: return KERN_FAILURE;
682: }
683:
684: old = *whichp;
685: *whichp = port;
686: itk_unlock(task);
687:
688: if (IP_VALID(old))
689: ipc_port_release_send(old);
690: return KERN_SUCCESS;
691: }
692:
693: /*
694: * Routine: thread_get_special_port [kernel call]
695: * Purpose:
696: * Clones a send right for one of the thread's
697: * special ports.
698: * Conditions:
699: * Nothing locked.
700: * Returns:
701: * KERN_SUCCESS Extracted a send right.
702: * KERN_INVALID_ARGUMENT The thread is null.
703: * KERN_FAILURE The thread is dead.
704: * KERN_INVALID_ARGUMENT Invalid special port.
705: */
706:
707: kern_return_t
708: thread_get_special_port(thread, which, portp)
709: thread_t thread;
710: int which;
711: ipc_port_t *portp;
712: {
713: ipc_port_t *whichp;
714: ipc_port_t port;
715:
716: if (thread == ITH_NULL)
717: return KERN_INVALID_ARGUMENT;
718:
719: switch (which) {
720: case THREAD_KERNEL_PORT:
721: whichp = &thread->ith_sself;
722: break;
723:
724: case THREAD_EXCEPTION_PORT:
725: whichp = &thread->ith_exception;
726: break;
727:
728: default:
729: return KERN_INVALID_ARGUMENT;
730: }
731:
732: ith_lock(thread);
733: if (thread->ith_self == IP_NULL) {
734: ith_unlock(thread);
735: return KERN_FAILURE;
736: }
737:
738: port = ipc_port_copy_send(*whichp);
739: ith_unlock(thread);
740:
741: *portp = port;
742: return KERN_SUCCESS;
743: }
744:
745: /*
746: * Routine: thread_set_special_port [kernel call]
747: * Purpose:
748: * Changes one of the thread's special ports,
749: * setting it to the supplied send right.
750: * Conditions:
751: * Nothing locked. If successful, consumes
752: * the supplied send right.
753: * Returns:
754: * KERN_SUCCESS Changed the special port.
755: * KERN_INVALID_ARGUMENT The thread is null.
756: * KERN_FAILURE The thread is dead.
757: * KERN_INVALID_ARGUMENT Invalid special port.
758: */
759:
760: kern_return_t
761: thread_set_special_port(thread, which, port)
762: thread_t thread;
763: int which;
764: ipc_port_t port;
765: {
766: ipc_port_t *whichp;
767: ipc_port_t old;
768:
769: if (thread == ITH_NULL)
770: return KERN_INVALID_ARGUMENT;
771:
772: switch (which) {
773: case THREAD_KERNEL_PORT:
774: whichp = &thread->ith_sself;
775: break;
776:
777: case THREAD_EXCEPTION_PORT:
778: whichp = &thread->ith_exception;
779: break;
780:
781: default:
782: return KERN_INVALID_ARGUMENT;
783: }
784:
785: ith_lock(thread);
786: if (thread->ith_self == IP_NULL) {
787: ith_unlock(thread);
788: return KERN_FAILURE;
789: }
790:
791: old = *whichp;
792: *whichp = port;
793: ith_unlock(thread);
794:
795: if (IP_VALID(old))
796: ipc_port_release_send(old);
797: return KERN_SUCCESS;
798: }
799:
800: /*
801: * Routine: mach_ports_register [kernel call]
802: * Purpose:
803: * Stash a handful of port send rights in the task.
804: * Child tasks will inherit these rights, but they
805: * must use mach_ports_lookup to acquire them.
806: *
807: * The rights are supplied in a (wired) kalloc'd segment.
808: * Rights which aren't supplied are assumed to be null.
809: * Conditions:
810: * Nothing locked. If successful, consumes
811: * the supplied rights and memory.
812: * Returns:
813: * KERN_SUCCESS Stashed the port rights.
814: * KERN_INVALID_ARGUMENT The task is null.
815: * KERN_INVALID_ARGUMENT The task is dead.
816: * KERN_INVALID_ARGUMENT Too many port rights supplied.
817: */
818:
819: kern_return_t
820: mach_ports_register(
821: task_t task,
822: mach_port_array_t memory,
823: mach_msg_type_number_t portsCnt)
824: {
825: ipc_port_t ports[TASK_PORT_REGISTER_MAX];
826: int i;
827:
828: if ((task == TASK_NULL) ||
829: (portsCnt > TASK_PORT_REGISTER_MAX))
830: return KERN_INVALID_ARGUMENT;
831:
832: /*
833: * Pad the port rights with nulls.
834: */
835:
836: for (i = 0; i < portsCnt; i++)
1.1.1.4 ! root 837: ports[i] = (ipc_port_t)memory[i];
1.1 root 838: for (; i < TASK_PORT_REGISTER_MAX; i++)
839: ports[i] = IP_NULL;
840:
841: itk_lock(task);
842: if (task->itk_self == IP_NULL) {
843: itk_unlock(task);
844: return KERN_INVALID_ARGUMENT;
845: }
846:
847: /*
848: * Replace the old send rights with the new.
849: * Release the old rights after unlocking.
850: */
851:
852: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) {
853: ipc_port_t old;
854:
855: old = task->itk_registered[i];
856: task->itk_registered[i] = ports[i];
857: ports[i] = old;
858: }
859:
860: itk_unlock(task);
861:
862: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
863: if (IP_VALID(ports[i]))
864: ipc_port_release_send(ports[i]);
865:
866: /*
867: * Now that the operation is known to be successful,
868: * we can free the memory.
869: */
870:
871: if (portsCnt != 0)
872: kfree((vm_offset_t) memory,
873: (vm_size_t) (portsCnt * sizeof(mach_port_t)));
874:
875: return KERN_SUCCESS;
876: }
877:
878: /*
879: * Routine: mach_ports_lookup [kernel call]
880: * Purpose:
881: * Retrieves (clones) the stashed port send rights.
882: * Conditions:
883: * Nothing locked. If successful, the caller gets
884: * rights and memory.
885: * Returns:
886: * KERN_SUCCESS Retrieved the send rights.
887: * KERN_INVALID_ARGUMENT The task is null.
888: * KERN_INVALID_ARGUMENT The task is dead.
889: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
890: */
891:
892: kern_return_t
893: mach_ports_lookup(task, portsp, portsCnt)
894: task_t task;
895: ipc_port_t **portsp;
896: mach_msg_type_number_t *portsCnt;
897: {
898: vm_offset_t memory;
899: vm_size_t size;
900: ipc_port_t *ports;
901: int i;
902:
903: if (task == TASK_NULL)
904: return KERN_INVALID_ARGUMENT;
905:
906: size = (vm_size_t) (TASK_PORT_REGISTER_MAX * sizeof(ipc_port_t));
907:
908: memory = kalloc(size);
909: if (memory == 0)
910: return KERN_RESOURCE_SHORTAGE;
911:
912: itk_lock(task);
913: if (task->itk_self == IP_NULL) {
914: itk_unlock(task);
915:
916: kfree(memory, size);
917: return KERN_INVALID_ARGUMENT;
918: }
919:
920: ports = (ipc_port_t *) memory;
921:
922: /*
923: * Clone port rights. Because kalloc'd memory
924: * is wired, we won't fault while holding the task lock.
925: */
926:
927: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
928: ports[i] = ipc_port_copy_send(task->itk_registered[i]);
929:
930: itk_unlock(task);
931:
1.1.1.2 root 932: *portsp = ports;
1.1 root 933: *portsCnt = TASK_PORT_REGISTER_MAX;
934: return KERN_SUCCESS;
935: }
936:
937: /*
938: * Routine: convert_port_to_task
939: * Purpose:
940: * Convert from a port to a task.
941: * Doesn't consume the port ref; produces a task ref,
942: * which may be null.
943: * Conditions:
944: * Nothing locked.
945: */
946:
947: task_t
948: convert_port_to_task(
949: ipc_port_t port)
950: {
951: task_t task = TASK_NULL;
952:
953: if (IP_VALID(port)) {
954: ip_lock(port);
955: if (ip_active(port) &&
956: (ip_kotype(port) == IKOT_TASK)) {
957: task = (task_t) port->ip_kobject;
958: task_reference(task);
959: }
960: ip_unlock(port);
961: }
962:
963: return task;
964: }
965:
966: /*
967: * Routine: convert_port_to_space
968: * Purpose:
969: * Convert from a port to a space.
970: * Doesn't consume the port ref; produces a space ref,
971: * which may be null.
972: * Conditions:
973: * Nothing locked.
974: */
975:
976: ipc_space_t
977: convert_port_to_space(
978: ipc_port_t port)
979: {
980: ipc_space_t space = IS_NULL;
981:
982: if (IP_VALID(port)) {
983: ip_lock(port);
984: if (ip_active(port) &&
985: (ip_kotype(port) == IKOT_TASK)) {
986: space = ((task_t) port->ip_kobject)->itk_space;
987: is_reference(space);
988: }
989: ip_unlock(port);
990: }
991:
992: return space;
993: }
994:
995: /*
996: * Routine: convert_port_to_map
997: * Purpose:
998: * Convert from a port to a map.
999: * Doesn't consume the port ref; produces a map ref,
1000: * which may be null.
1001: * Conditions:
1002: * Nothing locked.
1003: */
1004:
1005: vm_map_t
1006: convert_port_to_map(port)
1007: ipc_port_t port;
1008: {
1009: vm_map_t map = VM_MAP_NULL;
1010:
1011: if (IP_VALID(port)) {
1012: ip_lock(port);
1013: if (ip_active(port) &&
1014: (ip_kotype(port) == IKOT_TASK)) {
1015: map = ((task_t) port->ip_kobject)->map;
1016: vm_map_reference(map);
1017: }
1018: ip_unlock(port);
1019: }
1020:
1021: return map;
1022: }
1023:
1024: /*
1025: * Routine: convert_port_to_thread
1026: * Purpose:
1027: * Convert from a port to a thread.
1028: * Doesn't consume the port ref; produces a thread ref,
1029: * which may be null.
1030: * Conditions:
1031: * Nothing locked.
1032: */
1033:
1034: thread_t
1035: convert_port_to_thread(port)
1036: ipc_port_t port;
1037: {
1038: thread_t thread = THREAD_NULL;
1039:
1040: if (IP_VALID(port)) {
1041: ip_lock(port);
1042: if (ip_active(port) &&
1043: (ip_kotype(port) == IKOT_THREAD)) {
1044: thread = (thread_t) port->ip_kobject;
1045: thread_reference(thread);
1046: }
1047: ip_unlock(port);
1048: }
1049:
1050: return thread;
1051: }
1052:
1053: /*
1054: * Routine: convert_task_to_port
1055: * Purpose:
1056: * Convert from a task to a port.
1057: * Consumes a task ref; produces a naked send right
1.1.1.2 root 1058: * which may be invalid.
1.1 root 1059: * Conditions:
1060: * Nothing locked.
1061: */
1062:
1063: ipc_port_t
1064: convert_task_to_port(task)
1065: task_t task;
1066: {
1067: ipc_port_t port;
1068:
1069: itk_lock(task);
1070: if (task->itk_self != IP_NULL)
1071: port = ipc_port_make_send(task->itk_self);
1072: else
1073: port = IP_NULL;
1074: itk_unlock(task);
1075:
1076: task_deallocate(task);
1077: return port;
1078: }
1079:
1080: /*
1081: * Routine: convert_thread_to_port
1082: * Purpose:
1083: * Convert from a thread to a port.
1084: * Consumes a thread ref; produces a naked send right
1085: * which may be invalid.
1086: * Conditions:
1087: * Nothing locked.
1088: */
1089:
1090: ipc_port_t
1091: convert_thread_to_port(thread)
1092: thread_t thread;
1093: {
1094: ipc_port_t port;
1095:
1096: ith_lock(thread);
1097: if (thread->ith_self != IP_NULL)
1098: port = ipc_port_make_send(thread->ith_self);
1099: else
1100: port = IP_NULL;
1101: ith_unlock(thread);
1102:
1103: thread_deallocate(thread);
1104: return port;
1105: }
1106:
1107: /*
1108: * Routine: space_deallocate
1109: * Purpose:
1110: * Deallocate a space ref produced by convert_port_to_space.
1111: * Conditions:
1112: * Nothing locked.
1113: */
1114:
1115: void
1116: space_deallocate(space)
1117: ipc_space_t space;
1118: {
1119: if (space != IS_NULL)
1120: is_release(space);
1121: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.