123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134 |
- /*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
- /*
- * File: ipc_tt.c
- * Purpose:
- * Task and thread related IPC functions.
- */
- #include <glue/gnulinux.h>
- #include <linux/printk.h>
- #include <mach/message.h>
- #include <mach/boolean.h>
- #include <mach/kern_return.h>
- #include <mach/mach_param.h>
- #include <mach/task_special_ports.h>
- #include <mach/thread_special_ports.h>
- #include <vm/vm_kern.h>
- #include <kern/debug.h>
- #include <kern/kalloc.h>
- #include <kern/task.h>
- #include <kern/thread.h>
- #include <kern/ipc_kobject.h>
- #include <kern/ipc_tt.h>
- #include <ipc/ipc_space.h>
- #include <ipc/ipc_table.h>
- #include <ipc/ipc_port.h>
- #include <ipc/ipc_right.h>
- #include <ipc/ipc_entry.h>
- #include <ipc/ipc_object.h>
- /*
- * Routine: ipc_task_init
- * Purpose:
- * Initialize a task's IPC state.
- *
- * If non-null, some state will be inherited from the parent.
- * The parent must be appropriately initialized.
- * Conditions:
- * Nothing locked.
- */
- void
- ipc_task_init(
- task_t task,
- task_t parent)
- {
- ipc_space_t space;
- ipc_port_t kport;
- kern_return_t kr;
- int i;
-
- //printk(KERN_DEBUG "ipc_task_init %p %p\n",task,parent);
- kr = ipc_space_create(&ipc_table_entries[0],&space);
- if (kr != KERN_SUCCESS)
- panic("ipc_task_init");
- kport = ipc_port_alloc_kernel();
- if (kport == IP_NULL)
- panic("ipc_task_init");
- itk_lock_init(task);
- task->itk_self = kport;
- task->itk_sself = ipc_port_make_send(kport);
- task->itk_space = space;
- if (parent == TASK_NULL) {
- task->itk_exception = IP_NULL;
- task->itk_bootstrap = IP_NULL;
- for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
- task->itk_registered[i] = IP_NULL;
- } else {
- itk_lock(parent);
- assert(parent->itk_self != IP_NULL);
- /* inherit registered ports */
- for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
- task->itk_registered[i] =
- ipc_port_copy_send(parent->itk_registered[i]);
- /* inherit exception and bootstrap ports */
- task->itk_exception =
- ipc_port_copy_send(parent->itk_exception);
- task->itk_bootstrap =
- ipc_port_copy_send(parent->itk_bootstrap);
- itk_unlock(parent);
- }
- }
- /*
- * Routine: ipc_task_enable
- * Purpose:
- * Enable a task for IPC access.
- * Conditions:
- * Nothing locked.
- */
- void
- ipc_task_enable(
- task_t task)
- {
- ipc_port_t kport;
- itk_lock(task);
- kport = task->itk_self;
- if (kport != IP_NULL)
- ipc_kobject_set(kport, (ipc_kobject_t) task, IKOT_TASK);
- itk_unlock(task);
- }
- /*
- * Routine: ipc_task_disable
- * Purpose:
- * Disable IPC access to a task.
- * Conditions:
- * Nothing locked.
- */
- void
- ipc_task_disable(
- task_t task)
- {
- ipc_port_t kport;
- itk_lock(task);
- kport = task->itk_self;
- if (kport != IP_NULL)
- ipc_kobject_set(kport, IKO_NULL, IKOT_NONE);
- itk_unlock(task);
- }
- /*
- * Routine: ipc_task_terminate
- * Purpose:
- * Clean up and destroy a task's IPC state.
- * Conditions:
- * Nothing locked. The task must be suspended.
- * (Or the current thread must be in the task.)
- */
- void
- ipc_task_terminate(
- task_t task)
- {
- ipc_port_t kport;
- int i;
- itk_lock(task);
- kport = task->itk_self;
- if (kport == IP_NULL) {
- /* the task is already terminated (can this happen?) */
- itk_unlock(task);
- return;
- }
- task->itk_self = IP_NULL;
- itk_unlock(task);
- /* release the naked send rights */
- if (IP_VALID(task->itk_sself))
- ipc_port_release_send(task->itk_sself);
- if (IP_VALID(task->itk_exception))
- ipc_port_release_send(task->itk_exception);
- if (IP_VALID(task->itk_bootstrap))
- ipc_port_release_send(task->itk_bootstrap);
- for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
- if (IP_VALID(task->itk_registered[i]))
- ipc_port_release_send(task->itk_registered[i]);
- /* destroy the space, leaving just a reference for it */
- ipc_space_destroy(task->itk_space);
- /* destroy the kernel port */
- ipc_port_dealloc_kernel(kport);
- }
- /*
- * Routine: ipc_thread_init
- * Purpose:
- * Initialize a thread's IPC state.
- * Conditions:
- * Nothing locked.
- */
- void
- ipc_thread_init(thread_t thread)
- {
- ipc_port_t kport;
- kport = ipc_port_alloc_kernel();
- if (kport == IP_NULL)
- panic("ipc_thread_init");
- ipc_thread_links_init(thread);
- ipc_kmsg_queue_init(&thread->ith_messages);
- ith_lock_init(thread);
- thread->ith_self = kport;
- thread->ith_sself = ipc_port_make_send(kport);
- thread->ith_exception = IP_NULL;
- thread->ith_mig_reply = MACH_PORT_NULL;
- thread->ith_rpc_reply = IP_NULL;
- }
- /*
- * Routine: ipc_thread_enable
- * Purpose:
- * Enable a thread for IPC access.
- * Conditions:
- * Nothing locked.
- */
- void
- ipc_thread_enable(thread_t thread)
- {
- ipc_port_t kport;
- ith_lock(thread);
- kport = thread->ith_self;
- if (kport != IP_NULL)
- ipc_kobject_set(kport, (ipc_kobject_t) thread, IKOT_THREAD);
- ith_unlock(thread);
- }
- /*
- * Routine: ipc_thread_disable
- * Purpose:
- * Disable IPC access to a thread.
- * Conditions:
- * Nothing locked.
- */
- void
- ipc_thread_disable(thread_t thread)
- {
- ipc_port_t kport;
- ith_lock(thread);
- kport = thread->ith_self;
- if (kport != IP_NULL)
- ipc_kobject_set(kport, IKO_NULL, IKOT_NONE);
- ith_unlock(thread);
- }
- /*
- * Routine: ipc_thread_terminate
- * Purpose:
- * Clean up and destroy a thread's IPC state.
- * Conditions:
- * Nothing locked. The thread must be suspended.
- * (Or be the current thread.)
- */
- void
- ipc_thread_terminate(thread_t thread)
- {
- ipc_port_t kport;
- ith_lock(thread);
- kport = thread->ith_self;
- if (kport == IP_NULL) {
- /* the thread is already terminated (can this happen?) */
- ith_unlock(thread);
- return;
- }
- thread->ith_self = IP_NULL;
- ith_unlock(thread);
- assert(ipc_kmsg_queue_empty(&thread->ith_messages));
- /* release the naked send rights */
- if (IP_VALID(thread->ith_sself))
- ipc_port_release_send(thread->ith_sself);
- if (IP_VALID(thread->ith_exception))
- ipc_port_release_send(thread->ith_exception);
- /* destroy the kernel port */
- ipc_port_dealloc_kernel(kport);
- }
- #if 0
- /*
- * Routine: retrieve_task_self
- * Purpose:
- * Return a send right (possibly null/dead)
- * for the task's user-visible self port.
- * Conditions:
- * Nothing locked.
- */
- ipc_port_t
- retrieve_task_self(task)
- task_t task;
- {
- ipc_port_t port;
- assert(task != TASK_NULL);
- itk_lock(task);
- if (task->itk_self != IP_NULL)
- port = ipc_port_copy_send(task->itk_sself);
- else
- port = IP_NULL;
- itk_unlock(task);
- return port;
- }
- /*
- * Routine: retrieve_thread_self
- * Purpose:
- * Return a send right (possibly null/dead)
- * for the thread's user-visible self port.
- * Conditions:
- * Nothing locked.
- */
- ipc_port_t
- retrieve_thread_self(thread)
- thread_t thread;
- {
- ipc_port_t port;
- assert(thread != ITH_NULL);
- ith_lock(thread);
- if (thread->ith_self != IP_NULL)
- port = ipc_port_copy_send(thread->ith_sself);
- else
- port = IP_NULL;
- ith_unlock(thread);
- return port;
- }
- #endif /* 0 */
- /*
- * Routine: retrieve_task_self_fast
- * Purpose:
- * Optimized version of retrieve_task_self,
- * that only works for the current task.
- *
- * Return a send right (possibly null/dead)
- * for the task's user-visible self port.
- * Conditions:
- * Nothing locked.
- */
- ipc_port_t
- retrieve_task_self_fast(
- task_t task)
- {
- ipc_port_t port;
- assert(task == current_task());
- itk_lock(task);
- assert(task->itk_self != IP_NULL);
- if ((port = task->itk_sself) == task->itk_self) {
- /* no interposing */
- ip_lock(port);
- assert(ip_active(port));
- ip_reference(port);
- port->ip_srights++;
- ip_unlock(port);
- } else
- port = ipc_port_copy_send(port);
- itk_unlock(task);
- return port;
- }
- /*
- * Routine: retrieve_thread_self_fast
- * Purpose:
- * Optimized version of retrieve_thread_self,
- * that only works for the current thread.
- *
- * Return a send right (possibly null/dead)
- * for the thread's user-visible self port.
- * Conditions:
- * Nothing locked.
- */
- ipc_port_t
- retrieve_thread_self_fast(thread_t thread)
- {
- ipc_port_t port;
- assert(thread == current_thread());
- ith_lock(thread);
- assert(thread->ith_self != IP_NULL);
- if ((port = thread->ith_sself) == thread->ith_self) {
- /* no interposing */
- ip_lock(port);
- assert(ip_active(port));
- ip_reference(port);
- port->ip_srights++;
- ip_unlock(port);
- } else
- port = ipc_port_copy_send(port);
- ith_unlock(thread);
- return port;
- }
- #if 0
- /*
- * Routine: retrieve_task_exception
- * Purpose:
- * Return a send right (possibly null/dead)
- * for the task's exception port.
- * Conditions:
- * Nothing locked.
- */
- ipc_port_t
- retrieve_task_exception(task)
- task_t task;
- {
- ipc_port_t port;
- assert(task != TASK_NULL);
- itk_lock(task);
- if (task->itk_self != IP_NULL)
- port = ipc_port_copy_send(task->itk_exception);
- else
- port = IP_NULL;
- itk_unlock(task);
- return port;
- }
- /*
- * Routine: retrieve_thread_exception
- * Purpose:
- * Return a send right (possibly null/dead)
- * for the thread's exception port.
- * Conditions:
- * Nothing locked.
- */
- ipc_port_t
- retrieve_thread_exception(thread)
- thread_t thread;
- {
- ipc_port_t port;
- assert(thread != ITH_NULL);
- ith_lock(thread);
- if (thread->ith_self != IP_NULL)
- port = ipc_port_copy_send(thread->ith_exception);
- else
- port = IP_NULL;
- ith_unlock(thread);
- return port;
- }
- #endif /* 0 */
- /*
- * Routine: mach_task_self [mach trap]
- * Purpose:
- * Give the caller send rights for his own task port.
- * Conditions:
- * Nothing locked.
- * Returns:
- * MACH_PORT_NULL if there are any resource failures
- * or other errors.
- */
- mach_port_t
- mach_task_self(void)
- {
- task_t task = current_task();
- ipc_port_t sright;
- sright = retrieve_task_self_fast(task);
- return ipc_port_copyout_send(sright, task->itk_space);
- }
- /*
- * Routine: mach_thread_self [mach trap]
- * Purpose:
- * Give the caller send rights for his own thread port.
- * Conditions:
- * Nothing locked.
- * Returns:
- * MACH_PORT_NULL if there are any resource failures
- * or other errors.
- */
- mach_port_t
- mach_thread_self(void)
- {
- thread_t thread = current_thread();
- task_t task = thread->task;
- ipc_port_t sright;
- sright = retrieve_thread_self_fast(thread);
- return ipc_port_copyout_send(sright, task->itk_space);
- }
- /*
- * Routine: mach_reply_port [mach trap]
- * Purpose:
- * Allocate a port for the caller.
- * Conditions:
- * Nothing locked.
- * Returns:
- * MACH_PORT_NULL if there are any resource failures
- * or other errors.
- */
- mach_port_t
- mach_reply_port(void)
- {
- ipc_port_t port;
- mach_port_t name;
- kern_return_t kr;
- kr = ipc_port_alloc(current_task()->itk_space, &name, &port);
- if (kr == KERN_SUCCESS)
- ip_unlock(port);
- else
- name = MACH_PORT_NULL;
- return name;
- }
- /*
- * Routine: task_get_special_port [kernel call]
- * Purpose:
- * Clones a send right for one of the task's
- * special ports.
- * Conditions:
- * Nothing locked.
- * Returns:
- * KERN_SUCCESS Extracted a send right.
- * KERN_INVALID_ARGUMENT The task is null.
- * KERN_FAILURE The task/space is dead.
- * KERN_INVALID_ARGUMENT Invalid special port.
- */
- kern_return_t
- task_get_special_port(
- task_t task,
- int which,
- ipc_port_t *portp)
- {
- ipc_port_t *whichp;
- ipc_port_t port;
- if (task == TASK_NULL)
- return KERN_INVALID_ARGUMENT;
- switch (which) {
- case TASK_KERNEL_PORT:
- whichp = &task->itk_sself;
- break;
- case TASK_EXCEPTION_PORT:
- whichp = &task->itk_exception;
- break;
- case TASK_BOOTSTRAP_PORT:
- whichp = &task->itk_bootstrap;
- break;
- default:
- return KERN_INVALID_ARGUMENT;
- }
- itk_lock(task);
- if (task->itk_self == IP_NULL) {
- itk_unlock(task);
- return KERN_FAILURE;
- }
- port = ipc_port_copy_send(*whichp);
- itk_unlock(task);
- *portp = port;
- return KERN_SUCCESS;
- }
- /*
- * Routine: task_set_special_port [kernel call]
- * Purpose:
- * Changes one of the task's special ports,
- * setting it to the supplied send right.
- * Conditions:
- * Nothing locked. If successful, consumes
- * the supplied send right.
- * Returns:
- * KERN_SUCCESS Changed the special port.
- * KERN_INVALID_ARGUMENT The task is null.
- * KERN_FAILURE The task/space is dead.
- * KERN_INVALID_ARGUMENT Invalid special port.
- */
- kern_return_t
- task_set_special_port(
- task_t task,
- int which,
- const ipc_port_t port)
- {
- ipc_port_t *whichp;
- ipc_port_t old;
- if (task == TASK_NULL)
- return KERN_INVALID_ARGUMENT;
- switch (which) {
- case TASK_KERNEL_PORT:
- whichp = &task->itk_sself;
- break;
- case TASK_EXCEPTION_PORT:
- whichp = &task->itk_exception;
- break;
- case TASK_BOOTSTRAP_PORT:
- whichp = &task->itk_bootstrap;
- break;
- default:
- return KERN_INVALID_ARGUMENT;
- }
- itk_lock(task);
- if (task->itk_self == IP_NULL) {
- itk_unlock(task);
- return KERN_FAILURE;
- }
- old = *whichp;
- *whichp = port;
- itk_unlock(task);
- if (IP_VALID(old))
- ipc_port_release_send(old);
- return KERN_SUCCESS;
- }
- /*
- * Routine: thread_get_special_port [kernel call]
- * Purpose:
- * Clones a send right for one of the thread's
- * special ports.
- * Conditions:
- * Nothing locked.
- * Returns:
- * KERN_SUCCESS Extracted a send right.
- * KERN_INVALID_ARGUMENT The thread is null.
- * KERN_FAILURE The thread is dead.
- * KERN_INVALID_ARGUMENT Invalid special port.
- */
- kern_return_t
- thread_get_special_port(
- thread_t thread,
- int which,
- ipc_port_t *portp)
- {
- ipc_port_t *whichp;
- ipc_port_t port;
- if (thread == ITH_NULL)
- return KERN_INVALID_ARGUMENT;
- switch (which) {
- case THREAD_KERNEL_PORT:
- whichp = &thread->ith_sself;
- break;
- case THREAD_EXCEPTION_PORT:
- whichp = &thread->ith_exception;
- break;
- default:
- return KERN_INVALID_ARGUMENT;
- }
- ith_lock(thread);
- if (thread->ith_self == IP_NULL) {
- ith_unlock(thread);
- return KERN_FAILURE;
- }
- port = ipc_port_copy_send(*whichp);
- ith_unlock(thread);
- *portp = port;
- return KERN_SUCCESS;
- }
- /*
- * Routine: thread_set_special_port [kernel call]
- * Purpose:
- * Changes one of the thread's special ports,
- * setting it to the supplied send right.
- * Conditions:
- * Nothing locked. If successful, consumes
- * the supplied send right.
- * Returns:
- * KERN_SUCCESS Changed the special port.
- * KERN_INVALID_ARGUMENT The thread is null.
- * KERN_FAILURE The thread is dead.
- * KERN_INVALID_ARGUMENT Invalid special port.
- */
- kern_return_t
- thread_set_special_port(
- thread_t thread,
- int which,
- ipc_port_t port)
- {
- ipc_port_t *whichp;
- ipc_port_t old;
- if (thread == ITH_NULL)
- return KERN_INVALID_ARGUMENT;
- switch (which) {
- case THREAD_KERNEL_PORT:
- whichp = &thread->ith_sself;
- break;
- case THREAD_EXCEPTION_PORT:
- whichp = &thread->ith_exception;
- break;
- default:
- return KERN_INVALID_ARGUMENT;
- }
- ith_lock(thread);
- if (thread->ith_self == IP_NULL) {
- ith_unlock(thread);
- return KERN_FAILURE;
- }
- old = *whichp;
- *whichp = port;
- ith_unlock(thread);
- if (IP_VALID(old))
- ipc_port_release_send(old);
- return KERN_SUCCESS;
- }
- /*
- * Routine: mach_ports_register [kernel call]
- * Purpose:
- * Stash a handful of port send rights in the task.
- * Child tasks will inherit these rights, but they
- * must use mach_ports_lookup to acquire them.
- *
- * The rights are supplied in a (wired) kalloc'd segment.
- * Rights which aren't supplied are assumed to be null.
- * Conditions:
- * Nothing locked. If successful, consumes
- * the supplied rights and memory.
- * Returns:
- * KERN_SUCCESS Stashed the port rights.
- * KERN_INVALID_ARGUMENT The task is null.
- * KERN_INVALID_ARGUMENT The task is dead.
- * KERN_INVALID_ARGUMENT Too many port rights supplied.
- */
- kern_return_t
- mach_ports_register(
- task_t task,
- mach_port_array_t memory,
- mach_msg_type_number_t portsCnt)
- {
- ipc_port_t ports[TASK_PORT_REGISTER_MAX];
- unsigned i;
- if ((task == TASK_NULL) ||
- (portsCnt > TASK_PORT_REGISTER_MAX))
- return KERN_INVALID_ARGUMENT;
- /*
- * Pad the port rights with nulls.
- */
- for (i = 0; i < portsCnt; i++)
- ports[i] = (ipc_port_t)memory[i];
- for (; i < TASK_PORT_REGISTER_MAX; i++)
- ports[i] = IP_NULL;
- itk_lock(task);
- if (task->itk_self == IP_NULL) {
- itk_unlock(task);
- return KERN_INVALID_ARGUMENT;
- }
- /*
- * Replace the old send rights with the new.
- * Release the old rights after unlocking.
- */
- for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) {
- ipc_port_t old;
- old = task->itk_registered[i];
- task->itk_registered[i] = ports[i];
- ports[i] = old;
- }
- itk_unlock(task);
- for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
- if (IP_VALID(ports[i]))
- ipc_port_release_send(ports[i]);
- /*
- * Now that the operation is known to be successful,
- * we can free the memory.
- */
- if (portsCnt != 0)
- kfree((vm_offset_t) memory,
- (vm_size_t) (portsCnt * sizeof(mach_port_t)));
- return KERN_SUCCESS;
- }
- /*
- * Routine: mach_ports_lookup [kernel call]
- * Purpose:
- * Retrieves (clones) the stashed port send rights.
- * Conditions:
- * Nothing locked. If successful, the caller gets
- * rights and memory.
- * Returns:
- * KERN_SUCCESS Retrieved the send rights.
- * KERN_INVALID_ARGUMENT The task is null.
- * KERN_INVALID_ARGUMENT The task is dead.
- * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
- */
- kern_return_t
- mach_ports_lookup(
- task_t task,
- ipc_port_t **portsp,
- mach_msg_type_number_t *portsCnt)
- {
- vm_offset_t memory;
- vm_size_t size;
- ipc_port_t *ports;
- int i;
- if (task == TASK_NULL)
- return KERN_INVALID_ARGUMENT;
- size = (vm_size_t) (TASK_PORT_REGISTER_MAX * sizeof(ipc_port_t));
- memory = kalloc(size);
- if (memory == 0)
- return KERN_RESOURCE_SHORTAGE;
- itk_lock(task);
- if (task->itk_self == IP_NULL) {
- itk_unlock(task);
- kfree(memory, size);
- return KERN_INVALID_ARGUMENT;
- }
- ports = (ipc_port_t *) memory;
- /*
- * Clone port rights. Because kalloc'd memory
- * is wired, we won't fault while holding the task lock.
- */
- for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
- ports[i] = ipc_port_copy_send(task->itk_registered[i]);
- itk_unlock(task);
- *portsp = ports;
- *portsCnt = TASK_PORT_REGISTER_MAX;
- return KERN_SUCCESS;
- }
- /*
- * Routine: convert_port_to_task
- * Purpose:
- * Convert from a port to a task.
- * Doesn't consume the port ref; produces a task ref,
- * which may be null.
- * Conditions:
- * Nothing locked.
- */
- #if 0
- task_t
- convert_port_to_task(
- ipc_port_t port)
- {
- task_t task = TASK_NULL;
- if (IP_VALID(port)) {
- ip_lock(port);
- if (ip_active(port) &&
- (ip_kotype(port) == IKOT_TASK)) {
- task = (task_t) port->ip_kobject;
- task_reference(task);
- }
- ip_unlock(port);
- }
- return task;
- }
- #endif
- /*
- * Routine: convert_port_to_space
- * Purpose:
- * Convert from a port to a space.
- * Doesn't consume the port ref; produces a space ref,
- * which may be null.
- * Conditions:
- * Nothing locked.
- */
- ipc_space_t
- convert_port_to_space(
- ipc_port_t port)
- {
- ipc_space_t space = IS_NULL;
- if (IP_VALID(port)) {
- ip_lock(port);
- if (ip_active(port) &&
- (ip_kotype(port) == IKOT_TASK)) {
- space = ((task_t) port->ip_kobject)->itk_space;
- is_reference(space);
- }
- ip_unlock(port);
- }
- return space;
- }
- /*
- * Routine: convert_port_to_map
- * Purpose:
- * Convert from a port to a map.
- * Doesn't consume the port ref; produces a map ref,
- * which may be null.
- * Conditions:
- * Nothing locked.
- */
- #if 0
- vm_map_t
- convert_port_to_map(ipc_port_t port)
- {
- vm_map_t map = VM_MAP_NULL;
- if (IP_VALID(port)) {
- ip_lock(port);
- if (ip_active(port) &&
- (ip_kotype(port) == IKOT_TASK)) {
- map = ((task_t) port->ip_kobject)->map;
- vm_map_reference(map);
- }
- ip_unlock(port);
- }
- return map;
- }
- #endif
- /*
- * Routine: convert_port_to_thread
- * Purpose:
- * Convert from a port to a thread.
- * Doesn't consume the port ref; produces a thread ref,
- * which may be null.
- * Conditions:
- * Nothing locked.
- */
- #if 0
- thread_t
- convert_port_to_thread(ipc_port_t port)
- {
- thread_t thread = THREAD_NULL;
- if (IP_VALID(port)) {
- ip_lock(port);
- if (ip_active(port) &&
- (ip_kotype(port) == IKOT_THREAD)) {
- thread = (thread_t) port->ip_kobject;
- thread_reference(thread);
- }
- ip_unlock(port);
- }
- return thread;
- }
- /*
- * Routine: convert_task_to_port
- * Purpose:
- * Convert from a task to a port.
- * Consumes a task ref; produces a naked send right
- * which may be invalid.
- * Conditions:
- * Nothing locked.
- */
- ipc_port_t
- convert_task_to_port(task_t task)
- {
- ipc_port_t port;
- itk_lock(task);
- if (task->itk_self != IP_NULL)
- port = ipc_port_make_send(task->itk_self);
- else
- port = IP_NULL;
- itk_unlock(task);
- task_deallocate(task);
- return port;
- }
- #endif
- /*
- * Routine: convert_thread_to_port
- * Purpose:
- * Convert from a thread to a port.
- * Consumes a thread ref; produces a naked send right
- * which may be invalid.
- * Conditions:
- * Nothing locked.
- */
- #if 0
- ipc_port_t
- convert_thread_to_port(thread_t thread)
- {
- ipc_port_t port;
- ith_lock(thread);
- if (thread->ith_self != IP_NULL)
- port = ipc_port_make_send(thread->ith_self);
- else
- port = IP_NULL;
- ith_unlock(thread);
- thread_deallocate(thread);
- return port;
- }
- #endif
- /*
- * Routine: space_deallocate
- * Purpose:
- * Deallocate a space ref produced by convert_port_to_space.
- * Conditions:
- * Nothing locked.
- */
- void
- space_deallocate(ipc_space_t space)
- {
- if (space != IS_NULL)
- is_release(space);
- }
- void* gnumach_task_create(void)
- {
- task_t task = 0;
- (void) task_create_kernel(kernel_task, FALSE, &task);
- return (void*)task;
- }
|