diff options
Diffstat (limited to 'kern/task.c')
-rw-r--r-- | kern/task.c | 190 |
1 files changed, 134 insertions, 56 deletions
diff --git a/kern/task.c b/kern/task.c index 114dd319..0f24e44d 100644 --- a/kern/task.c +++ b/kern/task.c @@ -37,6 +37,7 @@ #include <mach/vm_param.h> #include <mach/task_info.h> #include <mach/task_special_ports.h> +#include <mach_debug/mach_debug_types.h> #include <ipc/ipc_space.h> #include <ipc/ipc_types.h> #include <kern/debug.h> @@ -45,22 +46,24 @@ #include <kern/slab.h> #include <kern/kalloc.h> #include <kern/processor.h> +#include <kern/printf.h> #include <kern/sched_prim.h> /* for thread_wakeup */ #include <kern/ipc_tt.h> +#include <kern/syscall_emulation.h> +#include <kern/task_notify.user.h> #include <vm/vm_kern.h> /* for kernel_map, ipc_kernel_map */ #include <machine/machspl.h> /* for splsched */ task_t kernel_task = TASK_NULL; struct kmem_cache task_cache; -extern void eml_init(void); -extern void eml_task_reference(task_t, task_t); -extern void eml_task_deallocate(task_t); +/* Where to send notifications about newly created tasks. */ +ipc_port_t new_task_notification = NULL; void task_init(void) { kmem_cache_init(&task_cache, "task", sizeof(struct task), 0, - NULL, NULL, NULL, 0); + NULL, 0); eml_init(); machine_task_module_init (); @@ -71,6 +74,7 @@ void task_init(void) * for other initialization. (:-() */ (void) task_create(TASK_NULL, FALSE, &kernel_task); + (void) task_set_name(kernel_task, "gnumach"); } kern_return_t task_create( @@ -78,16 +82,15 @@ kern_return_t task_create( boolean_t inherit_memory, task_t *child_task) /* OUT */ { - register task_t new_task; - register processor_set_t pset; + task_t new_task; + processor_set_t pset; #if FAST_TAS int i; #endif new_task = (task_t) kmem_cache_alloc(&task_cache); - if (new_task == TASK_NULL) { - panic("task_create: no memory for task structure"); - } + if (new_task == TASK_NULL) + return KERN_RESOURCE_SHORTAGE; /* one ref for just being alive; one for our caller */ new_task->ref_count = 2; @@ -167,6 +170,21 @@ kern_return_t task_create( } #endif /* FAST_TAS */ + if (parent_task == TASK_NULL) + snprintf (new_task->name, sizeof new_task->name, "%p", + new_task); + else + snprintf (new_task->name, sizeof new_task->name, "(%.*s)", + sizeof new_task->name - 3, parent_task->name); + + if (new_task_notification != NULL) { + task_reference (new_task); + task_reference (parent_task); + mach_notify_new_task (new_task_notification, + convert_task_to_port (new_task), + convert_task_to_port (parent_task)); + } + ipc_task_enable(new_task); *child_task = new_task; @@ -181,10 +199,10 @@ kern_return_t task_create( * is never in this task. */ void task_deallocate( - register task_t task) + task_t task) { - register int c; - register processor_set_t pset; + int c; + processor_set_t pset; if (task == TASK_NULL) return; @@ -210,7 +228,7 @@ void task_deallocate( } void task_reference( - register task_t task) + task_t task) { if (task == TASK_NULL) return; @@ -227,11 +245,11 @@ void task_reference( * (kern/thread.c) about problems with terminating the "current task." */ kern_return_t task_terminate( - register task_t task) + task_t task) { - register thread_t thread, cur_thread; - register queue_head_t *list; - register task_t cur_task; + thread_t thread, cur_thread; + queue_head_t *list; + task_t cur_task; spl_t s; if (task == TASK_NULL) @@ -270,6 +288,7 @@ kern_return_t task_terminate( thread_terminate(cur_thread); return KERN_FAILURE; } + task_hold_locked(task); task->active = FALSE; queue_remove(list, cur_thread, thread_t, thread_list); thread_unlock(cur_thread); @@ -323,6 +342,7 @@ kern_return_t task_terminate( task_unlock(task); return KERN_FAILURE; } + task_hold_locked(task); task->active = FALSE; task_unlock(task); } @@ -333,9 +353,8 @@ kern_return_t task_terminate( * If this is the current task, the current thread will * be left running. */ - ipc_task_disable(task); - (void) task_hold(task); (void) task_dowait(task,TRUE); /* may block */ + ipc_task_disable(task); /* * Terminate each thread in the task. @@ -358,7 +377,7 @@ kern_return_t task_terminate( task_unlock(task); thread_force_terminate(thread); thread_deallocate(thread); - thread_block((void (*)()) 0); + thread_block(thread_no_continuation); task_lock(task); } task_unlock(task); @@ -400,20 +419,18 @@ kern_return_t task_terminate( * Suspend execution of the specified task. * This is a recursive-style suspension of the task, a count of * suspends is maintained. + * + * CONDITIONS: the task is locked and active. */ -kern_return_t task_hold( - register task_t task) +void task_hold_locked( + task_t task) { - register queue_head_t *list; - register thread_t thread, cur_thread; + queue_head_t *list; + thread_t thread, cur_thread; - cur_thread = current_thread(); + assert(task->active); - task_lock(task); - if (!task->active) { - task_unlock(task); - return KERN_FAILURE; - } + cur_thread = current_thread(); task->suspend_count++; @@ -427,6 +444,26 @@ kern_return_t task_hold( if (thread != cur_thread) thread_hold(thread); } +} + +/* + * task_hold: + * + * Suspend execution of the specified task. + * This is a recursive-style suspension of the task, a count of + * suspends is maintained. + */ +kern_return_t task_hold( + task_t task) +{ + task_lock(task); + if (!task->active) { + task_unlock(task); + return KERN_FAILURE; + } + + task_hold_locked(task); + task_unlock(task); return KERN_SUCCESS; } @@ -441,12 +478,12 @@ kern_return_t task_hold( * must_wait is true. */ kern_return_t task_dowait( - register task_t task, + task_t task, boolean_t must_wait) { - register queue_head_t *list; - register thread_t thread, cur_thread, prev_thread; - register kern_return_t ret = KERN_SUCCESS; + queue_head_t *list; + thread_t thread, cur_thread, prev_thread; + kern_return_t ret = KERN_SUCCESS; /* * Iterate through all the threads. @@ -493,10 +530,10 @@ kern_return_t task_dowait( } kern_return_t task_release( - register task_t task) + task_t task) { - register queue_head_t *list; - register thread_t thread, next; + queue_head_t *list; + thread_t thread, next; task_lock(task); if (!task->active) { @@ -624,9 +661,9 @@ kern_return_t task_threads( } kern_return_t task_suspend( - register task_t task) + task_t task) { - register boolean_t hold; + boolean_t hold; if (task == TASK_NULL) return KERN_INVALID_ARGUMENT; @@ -675,9 +712,9 @@ kern_return_t task_suspend( } kern_return_t task_resume( - register task_t task) + task_t task) { - register boolean_t release; + boolean_t release; if (task == TASK_NULL) return KERN_INVALID_ARGUMENT; @@ -717,7 +754,7 @@ kern_return_t task_info( switch (flavor) { case TASK_BASIC_INFO: { - register task_basic_info_t basic_info; + task_basic_info_t basic_info; /* Allow *task_info_count to be two words smaller than the usual amount, because creation_time is a new member @@ -746,7 +783,8 @@ kern_return_t task_info( = task->total_system_time.seconds; basic_info->system_time.microseconds = task->total_system_time.microseconds; - basic_info->creation_time = task->creation_time; + read_time_stamp(&task->creation_time, + &basic_info->creation_time); task_unlock(task); if (*task_info_count > TASK_BASIC_INFO_COUNT) @@ -756,7 +794,7 @@ kern_return_t task_info( case TASK_EVENTS_INFO: { - register task_events_info_t event_info; + task_events_info_t event_info; if (*task_info_count < TASK_EVENTS_INFO_COUNT) { return KERN_INVALID_ARGUMENT; @@ -764,7 +802,7 @@ kern_return_t task_info( event_info = (task_events_info_t) task_info_out; - task_lock(&task); + task_lock(task); event_info->faults = task->faults; event_info->zero_fills = task->zero_fills; event_info->reactivations = task->reactivations; @@ -772,7 +810,7 @@ kern_return_t task_info( event_info->cow_faults = task->cow_faults; event_info->messages_sent = task->messages_sent; event_info->messages_received = task->messages_received; - task_unlock(&task); + task_unlock(task); *task_info_count = TASK_EVENTS_INFO_COUNT; break; @@ -780,8 +818,8 @@ kern_return_t task_info( case TASK_THREAD_TIMES_INFO: { - register task_thread_times_info_t times_info; - register thread_t thread; + task_thread_times_info_t times_info; + thread_t thread; if (*task_info_count < TASK_THREAD_TIMES_INFO_COUNT) { return KERN_INVALID_ARGUMENT; @@ -837,9 +875,9 @@ task_assign( boolean_t assign_threads) { kern_return_t ret = KERN_SUCCESS; - register thread_t thread, prev_thread; - register queue_head_t *list; - register processor_set_t pset; + thread_t thread, prev_thread; + queue_head_t *list; + processor_set_t pset; if (task == TASK_NULL || new_pset == PROCESSOR_SET_NULL) { return KERN_INVALID_ARGUMENT; @@ -855,7 +893,7 @@ task_assign( task->assign_active = TRUE; assert_wait((event_t)&task->assign_active, TRUE); task_unlock(task); - thread_block((void (*)()) 0); + thread_block(thread_no_continuation); task_lock(task); } @@ -1026,6 +1064,9 @@ kern_return_t task_get_assignment( task_t task, processor_set_t *pset) { + if (task == TASK_NULL) + return KERN_INVALID_ARGUMENT; + if (!task->active) return KERN_FAILURE; @@ -1055,8 +1096,8 @@ task_priority( task->priority = priority; if (change_threads) { - register thread_t thread; - register queue_head_t *list; + thread_t thread; + queue_head_t *list; list = &task->thread_list; queue_iterate(list, thread, thread_t, thread_list) { @@ -1071,6 +1112,22 @@ task_priority( } /* + * task_set_name + * + * Set the name of task TASK to NAME. This is a debugging aid. + * NAME will be used in error messages printed by the kernel. + */ +kern_return_t +task_set_name( + task_t task, + kernel_debug_name_t name) +{ + strncpy(task->name, name, sizeof task->name - 1); + task->name[sizeof task->name - 1] = '\0'; + return KERN_SUCCESS; +} + +/* * task_collect_scan: * * Attempt to free resources owned by tasks. @@ -1078,7 +1135,7 @@ task_priority( void task_collect_scan(void) { - register task_t task, prev_task; + task_t task, prev_task; processor_set_t pset, prev_pset; prev_task = TASK_NULL; @@ -1209,6 +1266,27 @@ task_ras_control( break; } task_unlock(task); -#endif +#endif /* FAST_TAS */ return ret; } + +/* + * register_new_task_notification + * + * Register a port to which a notification about newly created + * tasks are sent. + */ +kern_return_t +register_new_task_notification( + const host_t host, + ipc_port_t notification) +{ + if (host == HOST_NULL) + return KERN_INVALID_HOST; + + if (new_task_notification != NULL) + return KERN_NO_ACCESS; + + new_task_notification = notification; + return KERN_SUCCESS; +} |