|
|
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
1.1.1.5 ! root 216: ipc_thread_init(thread_t thread)
1.1 root 217: {
218: ipc_port_t kport;
219:
220: kport = ipc_port_alloc_kernel();
221: if (kport == IP_NULL)
222: panic("ipc_thread_init");
223:
224: ipc_thread_links_init(thread);
225: ipc_kmsg_queue_init(&thread->ith_messages);
226:
227: ith_lock_init(thread);
228: thread->ith_self = kport;
229: thread->ith_sself = ipc_port_make_send(kport);
230: thread->ith_exception = IP_NULL;
231:
232: thread->ith_mig_reply = MACH_PORT_NULL;
233: thread->ith_rpc_reply = IP_NULL;
234: }
235:
236: /*
237: * Routine: ipc_thread_enable
238: * Purpose:
239: * Enable a thread for IPC access.
240: * Conditions:
241: * Nothing locked.
242: */
243:
244: void
1.1.1.5 ! root 245: ipc_thread_enable(thread_t thread)
1.1 root 246: {
247: ipc_port_t kport;
248:
249: ith_lock(thread);
250: kport = thread->ith_self;
251: if (kport != IP_NULL)
252: ipc_kobject_set(kport, (ipc_kobject_t) thread, IKOT_THREAD);
253: ith_unlock(thread);
254: }
255:
256: /*
257: * Routine: ipc_thread_disable
258: * Purpose:
259: * Disable IPC access to a thread.
260: * Conditions:
261: * Nothing locked.
262: */
263:
264: void
1.1.1.5 ! root 265: ipc_thread_disable(thread_t thread)
1.1 root 266: {
267: ipc_port_t kport;
268:
269: ith_lock(thread);
270: kport = thread->ith_self;
271: if (kport != IP_NULL)
272: ipc_kobject_set(kport, IKO_NULL, IKOT_NONE);
273: ith_unlock(thread);
274: }
275:
276: /*
277: * Routine: ipc_thread_terminate
278: * Purpose:
279: * Clean up and destroy a thread's IPC state.
280: * Conditions:
281: * Nothing locked. The thread must be suspended.
282: * (Or be the current thread.)
283: */
284:
285: void
1.1.1.5 ! root 286: ipc_thread_terminate(thread_t thread)
1.1 root 287: {
288: ipc_port_t kport;
289:
290: ith_lock(thread);
291: kport = thread->ith_self;
292:
293: if (kport == IP_NULL) {
294: /* the thread is already terminated (can this happen?) */
295: ith_unlock(thread);
296: return;
297: }
298:
299: thread->ith_self = IP_NULL;
300: ith_unlock(thread);
301:
302: assert(ipc_kmsg_queue_empty(&thread->ith_messages));
303:
304: /* release the naked send rights */
305:
306: if (IP_VALID(thread->ith_sself))
307: ipc_port_release_send(thread->ith_sself);
308: if (IP_VALID(thread->ith_exception))
309: ipc_port_release_send(thread->ith_exception);
310:
311: /* destroy the kernel port */
312:
313: ipc_port_dealloc_kernel(kport);
314: }
315:
316: #if 0
317: /*
318: * Routine: retrieve_task_self
319: * Purpose:
320: * Return a send right (possibly null/dead)
321: * for the task's user-visible self port.
322: * Conditions:
323: * Nothing locked.
324: */
325:
326: ipc_port_t
327: retrieve_task_self(task)
328: task_t task;
329: {
330: ipc_port_t port;
331:
332: assert(task != TASK_NULL);
333:
334: itk_lock(task);
335: if (task->itk_self != IP_NULL)
336: port = ipc_port_copy_send(task->itk_sself);
337: else
338: port = IP_NULL;
339: itk_unlock(task);
340:
341: return port;
342: }
343:
344: /*
345: * Routine: retrieve_thread_self
346: * Purpose:
347: * Return a send right (possibly null/dead)
348: * for the thread's user-visible self port.
349: * Conditions:
350: * Nothing locked.
351: */
352:
353: ipc_port_t
354: retrieve_thread_self(thread)
355: thread_t thread;
356: {
357: ipc_port_t port;
358:
359: assert(thread != ITH_NULL);
360:
361: ith_lock(thread);
362: if (thread->ith_self != IP_NULL)
363: port = ipc_port_copy_send(thread->ith_sself);
364: else
365: port = IP_NULL;
366: ith_unlock(thread);
367:
368: return port;
369: }
1.1.1.3 root 370: #endif /* 0 */
1.1 root 371:
372: /*
373: * Routine: retrieve_task_self_fast
374: * Purpose:
375: * Optimized version of retrieve_task_self,
376: * that only works for the current task.
377: *
378: * Return a send right (possibly null/dead)
379: * for the task's user-visible self port.
380: * Conditions:
381: * Nothing locked.
382: */
383:
384: ipc_port_t
385: retrieve_task_self_fast(
1.1.1.5 ! root 386: task_t task)
1.1 root 387: {
1.1.1.5 ! root 388: ipc_port_t port;
1.1 root 389:
390: assert(task == current_task());
391:
392: itk_lock(task);
393: assert(task->itk_self != IP_NULL);
394:
395: if ((port = task->itk_sself) == task->itk_self) {
396: /* no interposing */
397:
398: ip_lock(port);
399: assert(ip_active(port));
400: ip_reference(port);
401: port->ip_srights++;
402: ip_unlock(port);
403: } else
404: port = ipc_port_copy_send(port);
405: itk_unlock(task);
406:
407: return port;
408: }
409:
410: /*
411: * Routine: retrieve_thread_self_fast
412: * Purpose:
413: * Optimized version of retrieve_thread_self,
414: * that only works for the current thread.
415: *
416: * Return a send right (possibly null/dead)
417: * for the thread's user-visible self port.
418: * Conditions:
419: * Nothing locked.
420: */
421:
422: ipc_port_t
1.1.1.5 ! root 423: retrieve_thread_self_fast(thread_t thread)
1.1 root 424: {
1.1.1.5 ! root 425: ipc_port_t port;
1.1 root 426:
427: assert(thread == current_thread());
428:
429: ith_lock(thread);
430: assert(thread->ith_self != IP_NULL);
431:
432: if ((port = thread->ith_sself) == thread->ith_self) {
433: /* no interposing */
434:
435: ip_lock(port);
436: assert(ip_active(port));
437: ip_reference(port);
438: port->ip_srights++;
439: ip_unlock(port);
440: } else
441: port = ipc_port_copy_send(port);
442: ith_unlock(thread);
443:
444: return port;
445: }
446:
447: #if 0
448: /*
449: * Routine: retrieve_task_exception
450: * Purpose:
451: * Return a send right (possibly null/dead)
452: * for the task's exception port.
453: * Conditions:
454: * Nothing locked.
455: */
456:
457: ipc_port_t
458: retrieve_task_exception(task)
459: task_t task;
460: {
461: ipc_port_t port;
462:
463: assert(task != TASK_NULL);
464:
465: itk_lock(task);
466: if (task->itk_self != IP_NULL)
467: port = ipc_port_copy_send(task->itk_exception);
468: else
469: port = IP_NULL;
470: itk_unlock(task);
471:
472: return port;
473: }
474:
475: /*
476: * Routine: retrieve_thread_exception
477: * Purpose:
478: * Return a send right (possibly null/dead)
479: * for the thread's exception port.
480: * Conditions:
481: * Nothing locked.
482: */
483:
484: ipc_port_t
485: retrieve_thread_exception(thread)
486: thread_t thread;
487: {
488: ipc_port_t port;
489:
490: assert(thread != ITH_NULL);
491:
492: ith_lock(thread);
493: if (thread->ith_self != IP_NULL)
494: port = ipc_port_copy_send(thread->ith_exception);
495: else
496: port = IP_NULL;
497: ith_unlock(thread);
498:
499: return port;
500: }
1.1.1.3 root 501: #endif /* 0 */
1.1 root 502:
503: /*
504: * Routine: mach_task_self [mach trap]
505: * Purpose:
506: * Give the caller send rights for his own task port.
507: * Conditions:
508: * Nothing locked.
509: * Returns:
510: * MACH_PORT_NULL if there are any resource failures
511: * or other errors.
512: */
513:
514: mach_port_t
515: mach_task_self(void)
516: {
517: task_t task = current_task();
518: ipc_port_t sright;
519:
520: sright = retrieve_task_self_fast(task);
521: return ipc_port_copyout_send(sright, task->itk_space);
522: }
523:
524: /*
525: * Routine: mach_thread_self [mach trap]
526: * Purpose:
527: * Give the caller send rights for his own thread port.
528: * Conditions:
529: * Nothing locked.
530: * Returns:
531: * MACH_PORT_NULL if there are any resource failures
532: * or other errors.
533: */
534:
535: mach_port_t
1.1.1.4 root 536: mach_thread_self(void)
1.1 root 537: {
538: thread_t thread = current_thread();
539: task_t task = thread->task;
540: ipc_port_t sright;
541:
542: sright = retrieve_thread_self_fast(thread);
543: return ipc_port_copyout_send(sright, task->itk_space);
544: }
545:
546: /*
547: * Routine: mach_reply_port [mach trap]
548: * Purpose:
549: * Allocate a port for the caller.
550: * Conditions:
551: * Nothing locked.
552: * Returns:
553: * MACH_PORT_NULL if there are any resource failures
554: * or other errors.
555: */
556:
557: mach_port_t
558: mach_reply_port(void)
559: {
560: ipc_port_t port;
561: mach_port_t name;
562: kern_return_t kr;
563:
564: kr = ipc_port_alloc(current_task()->itk_space, &name, &port);
565: if (kr == KERN_SUCCESS)
566: ip_unlock(port);
567: else
568: name = MACH_PORT_NULL;
569:
570: return name;
571: }
572:
573: /*
574: * Routine: task_get_special_port [kernel call]
575: * Purpose:
576: * Clones a send right for one of the task's
577: * special ports.
578: * Conditions:
579: * Nothing locked.
580: * Returns:
581: * KERN_SUCCESS Extracted a send right.
582: * KERN_INVALID_ARGUMENT The task is null.
583: * KERN_FAILURE The task/space is dead.
584: * KERN_INVALID_ARGUMENT Invalid special port.
585: */
586:
587: kern_return_t
588: task_get_special_port(
589: task_t task,
590: int which,
591: ipc_port_t *portp)
592: {
593: ipc_port_t *whichp;
594: ipc_port_t port;
595:
596: if (task == TASK_NULL)
597: return KERN_INVALID_ARGUMENT;
598:
599: switch (which) {
600: case TASK_KERNEL_PORT:
601: whichp = &task->itk_sself;
602: break;
603:
604: case TASK_EXCEPTION_PORT:
605: whichp = &task->itk_exception;
606: break;
607:
608: case TASK_BOOTSTRAP_PORT:
609: whichp = &task->itk_bootstrap;
610: break;
611:
612: default:
613: return KERN_INVALID_ARGUMENT;
614: }
615:
616: itk_lock(task);
617: if (task->itk_self == IP_NULL) {
618: itk_unlock(task);
619: return KERN_FAILURE;
620: }
621:
622: port = ipc_port_copy_send(*whichp);
623: itk_unlock(task);
624:
625: *portp = port;
626: return KERN_SUCCESS;
627: }
628:
629: /*
630: * Routine: task_set_special_port [kernel call]
631: * Purpose:
632: * Changes one of the task's special ports,
633: * setting it to the supplied send right.
634: * Conditions:
635: * Nothing locked. If successful, consumes
636: * the supplied send right.
637: * Returns:
638: * KERN_SUCCESS Changed the special port.
639: * KERN_INVALID_ARGUMENT The task is null.
640: * KERN_FAILURE The task/space is dead.
641: * KERN_INVALID_ARGUMENT Invalid special port.
642: */
643:
644: kern_return_t
645: task_set_special_port(
1.1.1.5 ! root 646: task_t task,
! 647: int which,
! 648: const ipc_port_t port)
1.1 root 649: {
650: ipc_port_t *whichp;
651: ipc_port_t old;
652:
653: if (task == TASK_NULL)
654: return KERN_INVALID_ARGUMENT;
655:
656: switch (which) {
657: case TASK_KERNEL_PORT:
658: whichp = &task->itk_sself;
659: break;
660:
661: case TASK_EXCEPTION_PORT:
662: whichp = &task->itk_exception;
663: break;
664:
665: case TASK_BOOTSTRAP_PORT:
666: whichp = &task->itk_bootstrap;
667: break;
668:
669: default:
670: return KERN_INVALID_ARGUMENT;
671: }
672:
673: itk_lock(task);
674: if (task->itk_self == IP_NULL) {
675: itk_unlock(task);
676: return KERN_FAILURE;
677: }
678:
679: old = *whichp;
680: *whichp = port;
681: itk_unlock(task);
682:
683: if (IP_VALID(old))
684: ipc_port_release_send(old);
685: return KERN_SUCCESS;
686: }
687:
688: /*
689: * Routine: thread_get_special_port [kernel call]
690: * Purpose:
691: * Clones a send right for one of the thread's
692: * special ports.
693: * Conditions:
694: * Nothing locked.
695: * Returns:
696: * KERN_SUCCESS Extracted a send right.
697: * KERN_INVALID_ARGUMENT The thread is null.
698: * KERN_FAILURE The thread is dead.
699: * KERN_INVALID_ARGUMENT Invalid special port.
700: */
701:
702: kern_return_t
1.1.1.5 ! root 703: thread_get_special_port(
! 704: thread_t thread,
! 705: int which,
! 706: ipc_port_t *portp)
1.1 root 707: {
708: ipc_port_t *whichp;
709: ipc_port_t port;
710:
711: if (thread == ITH_NULL)
712: return KERN_INVALID_ARGUMENT;
713:
714: switch (which) {
715: case THREAD_KERNEL_PORT:
716: whichp = &thread->ith_sself;
717: break;
718:
719: case THREAD_EXCEPTION_PORT:
720: whichp = &thread->ith_exception;
721: break;
722:
723: default:
724: return KERN_INVALID_ARGUMENT;
725: }
726:
727: ith_lock(thread);
728: if (thread->ith_self == IP_NULL) {
729: ith_unlock(thread);
730: return KERN_FAILURE;
731: }
732:
733: port = ipc_port_copy_send(*whichp);
734: ith_unlock(thread);
735:
736: *portp = port;
737: return KERN_SUCCESS;
738: }
739:
740: /*
741: * Routine: thread_set_special_port [kernel call]
742: * Purpose:
743: * Changes one of the thread's special ports,
744: * setting it to the supplied send right.
745: * Conditions:
746: * Nothing locked. If successful, consumes
747: * the supplied send right.
748: * Returns:
749: * KERN_SUCCESS Changed the special port.
750: * KERN_INVALID_ARGUMENT The thread is null.
751: * KERN_FAILURE The thread is dead.
752: * KERN_INVALID_ARGUMENT Invalid special port.
753: */
754:
755: kern_return_t
1.1.1.5 ! root 756: thread_set_special_port(
! 757: thread_t thread,
! 758: int which,
! 759: ipc_port_t port)
1.1 root 760: {
761: ipc_port_t *whichp;
762: ipc_port_t old;
763:
764: if (thread == ITH_NULL)
765: return KERN_INVALID_ARGUMENT;
766:
767: switch (which) {
768: case THREAD_KERNEL_PORT:
769: whichp = &thread->ith_sself;
770: break;
771:
772: case THREAD_EXCEPTION_PORT:
773: whichp = &thread->ith_exception;
774: break;
775:
776: default:
777: return KERN_INVALID_ARGUMENT;
778: }
779:
780: ith_lock(thread);
781: if (thread->ith_self == IP_NULL) {
782: ith_unlock(thread);
783: return KERN_FAILURE;
784: }
785:
786: old = *whichp;
787: *whichp = port;
788: ith_unlock(thread);
789:
790: if (IP_VALID(old))
791: ipc_port_release_send(old);
792: return KERN_SUCCESS;
793: }
794:
795: /*
796: * Routine: mach_ports_register [kernel call]
797: * Purpose:
798: * Stash a handful of port send rights in the task.
799: * Child tasks will inherit these rights, but they
800: * must use mach_ports_lookup to acquire them.
801: *
802: * The rights are supplied in a (wired) kalloc'd segment.
803: * Rights which aren't supplied are assumed to be null.
804: * Conditions:
805: * Nothing locked. If successful, consumes
806: * the supplied rights and memory.
807: * Returns:
808: * KERN_SUCCESS Stashed the port rights.
809: * KERN_INVALID_ARGUMENT The task is null.
810: * KERN_INVALID_ARGUMENT The task is dead.
811: * KERN_INVALID_ARGUMENT Too many port rights supplied.
812: */
813:
814: kern_return_t
815: mach_ports_register(
816: task_t task,
817: mach_port_array_t memory,
818: mach_msg_type_number_t portsCnt)
819: {
820: ipc_port_t ports[TASK_PORT_REGISTER_MAX];
821: int i;
822:
823: if ((task == TASK_NULL) ||
824: (portsCnt > TASK_PORT_REGISTER_MAX))
825: return KERN_INVALID_ARGUMENT;
826:
827: /*
828: * Pad the port rights with nulls.
829: */
830:
831: for (i = 0; i < portsCnt; i++)
1.1.1.4 root 832: ports[i] = (ipc_port_t)memory[i];
1.1 root 833: for (; i < TASK_PORT_REGISTER_MAX; i++)
834: ports[i] = IP_NULL;
835:
836: itk_lock(task);
837: if (task->itk_self == IP_NULL) {
838: itk_unlock(task);
839: return KERN_INVALID_ARGUMENT;
840: }
841:
842: /*
843: * Replace the old send rights with the new.
844: * Release the old rights after unlocking.
845: */
846:
847: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) {
848: ipc_port_t old;
849:
850: old = task->itk_registered[i];
851: task->itk_registered[i] = ports[i];
852: ports[i] = old;
853: }
854:
855: itk_unlock(task);
856:
857: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
858: if (IP_VALID(ports[i]))
859: ipc_port_release_send(ports[i]);
860:
861: /*
862: * Now that the operation is known to be successful,
863: * we can free the memory.
864: */
865:
866: if (portsCnt != 0)
867: kfree((vm_offset_t) memory,
868: (vm_size_t) (portsCnt * sizeof(mach_port_t)));
869:
870: return KERN_SUCCESS;
871: }
872:
873: /*
874: * Routine: mach_ports_lookup [kernel call]
875: * Purpose:
876: * Retrieves (clones) the stashed port send rights.
877: * Conditions:
878: * Nothing locked. If successful, the caller gets
879: * rights and memory.
880: * Returns:
881: * KERN_SUCCESS Retrieved the send rights.
882: * KERN_INVALID_ARGUMENT The task is null.
883: * KERN_INVALID_ARGUMENT The task is dead.
884: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
885: */
886:
887: kern_return_t
1.1.1.5 ! root 888: mach_ports_lookup(
! 889: task_t task,
! 890: ipc_port_t **portsp,
! 891: mach_msg_type_number_t *portsCnt)
1.1 root 892: {
893: vm_offset_t memory;
894: vm_size_t size;
895: ipc_port_t *ports;
896: int i;
897:
898: if (task == TASK_NULL)
899: return KERN_INVALID_ARGUMENT;
900:
901: size = (vm_size_t) (TASK_PORT_REGISTER_MAX * sizeof(ipc_port_t));
902:
903: memory = kalloc(size);
904: if (memory == 0)
905: return KERN_RESOURCE_SHORTAGE;
906:
907: itk_lock(task);
908: if (task->itk_self == IP_NULL) {
909: itk_unlock(task);
910:
911: kfree(memory, size);
912: return KERN_INVALID_ARGUMENT;
913: }
914:
915: ports = (ipc_port_t *) memory;
916:
917: /*
918: * Clone port rights. Because kalloc'd memory
919: * is wired, we won't fault while holding the task lock.
920: */
921:
922: for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
923: ports[i] = ipc_port_copy_send(task->itk_registered[i]);
924:
925: itk_unlock(task);
926:
1.1.1.2 root 927: *portsp = ports;
1.1 root 928: *portsCnt = TASK_PORT_REGISTER_MAX;
929: return KERN_SUCCESS;
930: }
931:
932: /*
933: * Routine: convert_port_to_task
934: * Purpose:
935: * Convert from a port to a task.
936: * Doesn't consume the port ref; produces a task ref,
937: * which may be null.
938: * Conditions:
939: * Nothing locked.
940: */
941:
942: task_t
943: convert_port_to_task(
944: ipc_port_t port)
945: {
946: task_t task = TASK_NULL;
947:
948: if (IP_VALID(port)) {
949: ip_lock(port);
950: if (ip_active(port) &&
951: (ip_kotype(port) == IKOT_TASK)) {
952: task = (task_t) port->ip_kobject;
953: task_reference(task);
954: }
955: ip_unlock(port);
956: }
957:
958: return task;
959: }
960:
961: /*
962: * Routine: convert_port_to_space
963: * Purpose:
964: * Convert from a port to a space.
965: * Doesn't consume the port ref; produces a space ref,
966: * which may be null.
967: * Conditions:
968: * Nothing locked.
969: */
970:
971: ipc_space_t
972: convert_port_to_space(
973: ipc_port_t port)
974: {
975: ipc_space_t space = IS_NULL;
976:
977: if (IP_VALID(port)) {
978: ip_lock(port);
979: if (ip_active(port) &&
980: (ip_kotype(port) == IKOT_TASK)) {
981: space = ((task_t) port->ip_kobject)->itk_space;
982: is_reference(space);
983: }
984: ip_unlock(port);
985: }
986:
987: return space;
988: }
989:
990: /*
991: * Routine: convert_port_to_map
992: * Purpose:
993: * Convert from a port to a map.
994: * Doesn't consume the port ref; produces a map ref,
995: * which may be null.
996: * Conditions:
997: * Nothing locked.
998: */
999:
1000: vm_map_t
1.1.1.5 ! root 1001: convert_port_to_map(ipc_port_t port)
1.1 root 1002: {
1003: vm_map_t map = VM_MAP_NULL;
1004:
1005: if (IP_VALID(port)) {
1006: ip_lock(port);
1007: if (ip_active(port) &&
1008: (ip_kotype(port) == IKOT_TASK)) {
1009: map = ((task_t) port->ip_kobject)->map;
1010: vm_map_reference(map);
1011: }
1012: ip_unlock(port);
1013: }
1014:
1015: return map;
1016: }
1017:
1018: /*
1019: * Routine: convert_port_to_thread
1020: * Purpose:
1021: * Convert from a port to a thread.
1022: * Doesn't consume the port ref; produces a thread ref,
1023: * which may be null.
1024: * Conditions:
1025: * Nothing locked.
1026: */
1027:
1028: thread_t
1.1.1.5 ! root 1029: convert_port_to_thread(ipc_port_t port)
1.1 root 1030: {
1031: thread_t thread = THREAD_NULL;
1032:
1033: if (IP_VALID(port)) {
1034: ip_lock(port);
1035: if (ip_active(port) &&
1036: (ip_kotype(port) == IKOT_THREAD)) {
1037: thread = (thread_t) port->ip_kobject;
1038: thread_reference(thread);
1039: }
1040: ip_unlock(port);
1041: }
1042:
1043: return thread;
1044: }
1045:
1046: /*
1047: * Routine: convert_task_to_port
1048: * Purpose:
1049: * Convert from a task to a port.
1050: * Consumes a task ref; produces a naked send right
1.1.1.2 root 1051: * which may be invalid.
1.1 root 1052: * Conditions:
1053: * Nothing locked.
1054: */
1055:
1056: ipc_port_t
1.1.1.5 ! root 1057: convert_task_to_port(task_t task)
1.1 root 1058: {
1059: ipc_port_t port;
1060:
1061: itk_lock(task);
1062: if (task->itk_self != IP_NULL)
1063: port = ipc_port_make_send(task->itk_self);
1064: else
1065: port = IP_NULL;
1066: itk_unlock(task);
1067:
1068: task_deallocate(task);
1069: return port;
1070: }
1071:
1072: /*
1073: * Routine: convert_thread_to_port
1074: * Purpose:
1075: * Convert from a thread to a port.
1076: * Consumes a thread ref; produces a naked send right
1077: * which may be invalid.
1078: * Conditions:
1079: * Nothing locked.
1080: */
1081:
1082: ipc_port_t
1.1.1.5 ! root 1083: convert_thread_to_port(thread_t thread)
1.1 root 1084: {
1085: ipc_port_t port;
1086:
1087: ith_lock(thread);
1088: if (thread->ith_self != IP_NULL)
1089: port = ipc_port_make_send(thread->ith_self);
1090: else
1091: port = IP_NULL;
1092: ith_unlock(thread);
1093:
1094: thread_deallocate(thread);
1095: return port;
1096: }
1097:
1098: /*
1099: * Routine: space_deallocate
1100: * Purpose:
1101: * Deallocate a space ref produced by convert_port_to_space.
1102: * Conditions:
1103: * Nothing locked.
1104: */
1105:
1106: void
1.1.1.5 ! root 1107: space_deallocate(ipc_space_t space)
1.1 root 1108: {
1109: if (space != IS_NULL)
1110: is_release(space);
1111: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.