X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/de355530ae67247cbd0da700edb3a2a1dae884c2..db6096698656d32db7df630594bd9617ee54f828:/osfmk/kern/processor.c?ds=sidebyside diff --git a/osfmk/kern/processor.c b/osfmk/kern/processor.c index 243afa7af..23a549611 100644 --- a/osfmk/kern/processor.c +++ b/osfmk/kern/processor.c @@ -1,23 +1,29 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2009 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ @@ -54,10 +60,9 @@ * processor.c: processor and processor_set manipulation routines. */ -#include - #include #include +#include #include #include #include @@ -77,453 +82,409 @@ * Exported interface */ #include +#include -/* - * Exported variables. - */ -struct processor_set default_pset; -struct processor processor_array[NCPUS]; - -int master_cpu = 0; - -processor_t master_processor; -processor_t processor_ptr[NCPUS]; - -/* Forwards */ -void pset_init( - processor_set_t pset); +struct processor_set pset0; +struct pset_node pset_node0; +decl_simple_lock_data(static,pset_node_lock) -void processor_init( - register processor_t pr, - int slot_num); +queue_head_t tasks; +queue_head_t terminated_tasks; /* To be used ONLY for stackshot. */ +int tasks_count; +queue_head_t threads; +int threads_count; +decl_lck_mtx_data(,tasks_threads_lock) -void pset_quanta_set( - processor_set_t pset); +processor_t processor_list; +unsigned int processor_count; +static processor_t processor_list_tail; +decl_simple_lock_data(,processor_list_lock) -kern_return_t processor_set_base( - processor_set_t pset, - policy_t policy, - policy_base_t base, - boolean_t change); +uint32_t processor_avail_count; -kern_return_t processor_set_limit( - processor_set_t pset, - policy_t policy, - policy_limit_t limit, - boolean_t change); +processor_t master_processor; +int master_cpu = 0; +boolean_t sched_stats_active = FALSE; +/* Forwards */ kern_return_t processor_set_things( processor_set_t pset, mach_port_t **thing_list, mach_msg_type_number_t *count, int type); - -/* - * Bootstrap the processor/pset system so the scheduler can run. - */ void -pset_sys_bootstrap(void) +processor_bootstrap(void) { - register int i; - - pset_init(&default_pset); - for (i = 0; i < NCPUS; i++) { - /* - * Initialize processor data structures. - * Note that cpu_to_processor(i) is processor_ptr[i]. - */ - processor_ptr[i] = &processor_array[i]; - processor_init(processor_ptr[i], i); - } - master_processor = cpu_to_processor(master_cpu); - master_processor->cpu_data = get_cpu_data(); - default_pset.active = TRUE; -} + pset_init(&pset0, &pset_node0); + pset_node0.psets = &pset0; -/* - * Initialize the given processor_set structure. - */ + simple_lock_init(&pset_node_lock, 0); -void pset_init( - register processor_set_t pset) -{ - register int i; - - /* setup run queue */ - simple_lock_init(&pset->runq.lock, ETAP_THREAD_PSET_RUNQ); - for (i = 0; i < NRQBM; i++) - pset->runq.bitmap[i] = 0; - setbit(MAXPRI - IDLEPRI, pset->runq.bitmap); - pset->runq.highq = IDLEPRI; - pset->runq.urgency = pset->runq.count = 0; - for (i = 0; i < NRQS; i++) - queue_init(&pset->runq.queues[i]); + queue_init(&tasks); + queue_init(&terminated_tasks); + queue_init(&threads); - queue_init(&pset->idle_queue); - pset->idle_count = 0; - queue_init(&pset->active_queue); - simple_lock_init(&pset->sched_lock, ETAP_THREAD_PSET_IDLE); - pset->run_count = 0; - pset->mach_factor = pset->load_average = 0; - pset->sched_load = 0; - queue_init(&pset->processors); - pset->processor_count = 0; - simple_lock_init(&pset->processors_lock, ETAP_THREAD_PSET); - queue_init(&pset->tasks); - pset->task_count = 0; - queue_init(&pset->threads); - pset->thread_count = 0; - pset->ref_count = 1; - pset->active = FALSE; - mutex_init(&pset->lock, ETAP_THREAD_PSET); - pset->pset_self = IP_NULL; - pset->pset_name_self = IP_NULL; - pset->set_quanta = 1; + simple_lock_init(&processor_list_lock, 0); + + master_processor = cpu_to_processor(master_cpu); - for (i = 0; i <= NCPUS; i++) - pset->machine_quanta[i] = 1; + processor_init(master_processor, master_cpu, &pset0); } /* - * Initialize the given processor structure for the processor in - * the slot specified by slot_num. + * Initialize the given processor for the cpu + * indicated by cpu_id, and assign to the + * specified processor set. */ void processor_init( - register processor_t p, - int slot_num) + processor_t processor, + int cpu_id, + processor_set_t pset) { - register int i; - - /* setup run queue */ - simple_lock_init(&p->runq.lock, ETAP_THREAD_PROC_RUNQ); - for (i = 0; i < NRQBM; i++) - p->runq.bitmap[i] = 0; - setbit(MAXPRI - IDLEPRI, p->runq.bitmap); - p->runq.highq = IDLEPRI; - p->runq.urgency = p->runq.count = 0; - for (i = 0; i < NRQS; i++) - queue_init(&p->runq.queues[i]); - - p->state = PROCESSOR_OFF_LINE; - p->current_pri = MINPRI; - p->next_thread = THREAD_NULL; - p->idle_thread = THREAD_NULL; - timer_call_setup(&p->quantum_timer, thread_quantum_expire, p); - p->slice_quanta = 0; - p->processor_set = PROCESSOR_SET_NULL; - p->processor_set_next = PROCESSOR_SET_NULL; - simple_lock_init(&p->lock, ETAP_THREAD_PROC); - p->processor_self = IP_NULL; - p->slot_num = slot_num; -} + if (processor != master_processor) { + /* Scheduler state deferred until sched_init() */ + SCHED(processor_init)(processor); + } -/* - * pset_deallocate: - * - * Remove one reference to the processor set. Destroy processor_set - * if this was the last reference. - */ -void -pset_deallocate( - processor_set_t pset) -{ - if (pset == PROCESSOR_SET_NULL) - return; + processor->state = PROCESSOR_OFF_LINE; + processor->active_thread = processor->next_thread = processor->idle_thread = THREAD_NULL; + processor->processor_set = pset; + processor->current_pri = MINPRI; + processor->current_thmode = TH_MODE_NONE; + processor->cpu_id = cpu_id; + timer_call_setup(&processor->quantum_timer, thread_quantum_expire, processor); + processor->deadline = UINT64_MAX; + processor->timeslice = 0; + processor->processor_meta = PROCESSOR_META_NULL; + processor->processor_self = IP_NULL; + processor_data_init(processor); + processor->processor_list = NULL; + + pset_lock(pset); + if (pset->cpu_set_count++ == 0) + pset->cpu_set_low = pset->cpu_set_hi = cpu_id; + else { + pset->cpu_set_low = (cpu_id < pset->cpu_set_low)? cpu_id: pset->cpu_set_low; + pset->cpu_set_hi = (cpu_id > pset->cpu_set_hi)? cpu_id: pset->cpu_set_hi; + } + pset_unlock(pset); - assert(pset == &default_pset); - return; + simple_lock(&processor_list_lock); + if (processor_list == NULL) + processor_list = processor; + else + processor_list_tail->processor_list = processor; + processor_list_tail = processor; + processor_count++; + simple_unlock(&processor_list_lock); } -/* - * pset_reference: - * - * Add one reference to the processor set. - */ void -pset_reference( - processor_set_t pset) +processor_meta_init( + processor_t processor, + processor_t primary) { - assert(pset == &default_pset); -} + processor_meta_t pmeta = primary->processor_meta; -#define pset_reference_locked(pset) assert(pset == &default_pset) + if (pmeta == PROCESSOR_META_NULL) { + pmeta = kalloc(sizeof (*pmeta)); -/* - * pset_remove_processor() removes a processor from a processor_set. - * It can only be called on the current processor. Caller must - * hold lock on current processor and processor set. - */ -void -pset_remove_processor( - processor_set_t pset, - processor_t processor) -{ - if (pset != processor->processor_set) - panic("pset_remove_processor: wrong pset"); + queue_init(&pmeta->idle_queue); + + pmeta->primary = primary; + } - queue_remove(&pset->processors, processor, processor_t, processors); - processor->processor_set = PROCESSOR_SET_NULL; - pset->processor_count--; - pset_quanta_set(pset); + processor->processor_meta = pmeta; } -/* - * pset_add_processor() adds a processor to a processor_set. - * It can only be called on the current processor. Caller must - * hold lock on curent processor and on pset. No reference counting on - * processors. Processor reference to pset is implicit. - */ -void -pset_add_processor( - processor_set_t pset, +processor_set_t +processor_pset( processor_t processor) { - queue_enter(&pset->processors, processor, processor_t, processors); - processor->processor_set = pset; - pset->processor_count++; - pset_quanta_set(pset); + return (processor->processor_set); } -/* - * pset_remove_task() removes a task from a processor_set. - * Caller must hold locks on pset and task (unless task has - * no references left, in which case just the pset lock is - * needed). Pset reference count is not decremented; - * caller must explicitly pset_deallocate. - */ -void -pset_remove_task( - processor_set_t pset, - task_t task) +pset_node_t +pset_node_root(void) { - if (pset != task->processor_set) - return; - - queue_remove(&pset->tasks, task, task_t, pset_tasks); - task->processor_set = PROCESSOR_SET_NULL; - pset->task_count--; + return &pset_node0; } -/* - * pset_add_task() adds a task to a processor_set. - * Caller must hold locks on pset and task. Pset references to - * tasks are implicit. - */ -void -pset_add_task( - processor_set_t pset, - task_t task) +processor_set_t +pset_create( + pset_node_t node) { - queue_enter(&pset->tasks, task, task_t, pset_tasks); - task->processor_set = pset; - pset->task_count++; - pset_reference_locked(pset); -} + processor_set_t *prev, pset = kalloc(sizeof (*pset)); -/* - * pset_remove_thread() removes a thread from a processor_set. - * Caller must hold locks on pset and thread (but only if thread - * has outstanding references that could be used to lookup the pset). - * The pset reference count is not decremented; caller must explicitly - * pset_deallocate. - */ -void -pset_remove_thread( - processor_set_t pset, - thread_t thread) -{ - queue_remove(&pset->threads, thread, thread_t, pset_threads); - thread->processor_set = PROCESSOR_SET_NULL; - pset->thread_count--; -} + if (pset != PROCESSOR_SET_NULL) { + pset_init(pset, node); -/* - * pset_add_thread() adds a thread to a processor_set. - * Caller must hold locks on pset and thread. Pset references to - * threads are implicit. - */ -void -pset_add_thread( - processor_set_t pset, - thread_t thread) -{ - queue_enter(&pset->threads, thread, thread_t, pset_threads); - thread->processor_set = pset; - pset->thread_count++; - pset_reference_locked(pset); + simple_lock(&pset_node_lock); + + prev = &node->psets; + while (*prev != PROCESSOR_SET_NULL) + prev = &(*prev)->pset_list; + + *prev = pset; + + simple_unlock(&pset_node_lock); + } + + return (pset); } /* - * thread_change_psets() changes the pset of a thread. Caller must - * hold locks on both psets and thread. The old pset must be - * explicitly pset_deallocat()'ed by caller. + * Initialize the given processor_set structure. */ void -thread_change_psets( - thread_t thread, - processor_set_t old_pset, - processor_set_t new_pset) +pset_init( + processor_set_t pset, + pset_node_t node) { - queue_remove(&old_pset->threads, thread, thread_t, pset_threads); - old_pset->thread_count--; - queue_enter(&new_pset->threads, thread, thread_t, pset_threads); - thread->processor_set = new_pset; - new_pset->thread_count++; - pset_reference_locked(new_pset); -} + if (pset != &pset0) { + /* Scheduler state deferred until sched_init() */ + SCHED(pset_init)(pset); + } + queue_init(&pset->active_queue); + queue_init(&pset->idle_queue); + pset->online_processor_count = 0; + pset_pri_init_hint(pset, PROCESSOR_NULL); + pset_count_init_hint(pset, PROCESSOR_NULL); + pset->cpu_set_low = pset->cpu_set_hi = 0; + pset->cpu_set_count = 0; + pset_lock_init(pset); + pset->pset_self = IP_NULL; + pset->pset_name_self = IP_NULL; + pset->pset_list = PROCESSOR_SET_NULL; + pset->node = node; +} kern_return_t processor_info_count( - processor_flavor_t flavor, + processor_flavor_t flavor, mach_msg_type_number_t *count) { - kern_return_t kr; - switch (flavor) { + case PROCESSOR_BASIC_INFO: *count = PROCESSOR_BASIC_INFO_COUNT; - return KERN_SUCCESS; + break; + case PROCESSOR_CPU_LOAD_INFO: *count = PROCESSOR_CPU_LOAD_INFO_COUNT; - return KERN_SUCCESS; + break; + default: - kr = cpu_info_count(flavor, count); - return kr; + return (cpu_info_count(flavor, count)); } + + return (KERN_SUCCESS); } kern_return_t processor_info( register processor_t processor, - processor_flavor_t flavor, - host_t *host, - processor_info_t info, + processor_flavor_t flavor, + host_t *host, + processor_info_t info, mach_msg_type_number_t *count) { - register int i, slot_num, state; - register processor_basic_info_t basic_info; - register processor_cpu_load_info_t cpu_load_info; - kern_return_t kr; + register int cpu_id, state; + kern_return_t result; if (processor == PROCESSOR_NULL) - return(KERN_INVALID_ARGUMENT); + return (KERN_INVALID_ARGUMENT); - slot_num = processor->slot_num; + cpu_id = processor->cpu_id; switch (flavor) { case PROCESSOR_BASIC_INFO: - { - if (*count < PROCESSOR_BASIC_INFO_COUNT) - return(KERN_FAILURE); - - basic_info = (processor_basic_info_t) info; - basic_info->cpu_type = machine_slot[slot_num].cpu_type; - basic_info->cpu_subtype = machine_slot[slot_num].cpu_subtype; - state = processor->state; - if (state == PROCESSOR_OFF_LINE) - basic_info->running = FALSE; - else - basic_info->running = TRUE; - basic_info->slot_num = slot_num; - if (processor == master_processor) - basic_info->is_master = TRUE; - else - basic_info->is_master = FALSE; - - *count = PROCESSOR_BASIC_INFO_COUNT; - *host = &realhost; - return(KERN_SUCCESS); - } + { + register processor_basic_info_t basic_info; + + if (*count < PROCESSOR_BASIC_INFO_COUNT) + return (KERN_FAILURE); + + basic_info = (processor_basic_info_t) info; + basic_info->cpu_type = slot_type(cpu_id); + basic_info->cpu_subtype = slot_subtype(cpu_id); + state = processor->state; + if (state == PROCESSOR_OFF_LINE) + basic_info->running = FALSE; + else + basic_info->running = TRUE; + basic_info->slot_num = cpu_id; + if (processor == master_processor) + basic_info->is_master = TRUE; + else + basic_info->is_master = FALSE; + + *count = PROCESSOR_BASIC_INFO_COUNT; + *host = &realhost; + + return (KERN_SUCCESS); + } + case PROCESSOR_CPU_LOAD_INFO: - { - if (*count < PROCESSOR_CPU_LOAD_INFO_COUNT) - return(KERN_FAILURE); + { + processor_cpu_load_info_t cpu_load_info; + timer_data_t idle_temp; + timer_t idle_state; + + if (*count < PROCESSOR_CPU_LOAD_INFO_COUNT) + return (KERN_FAILURE); + + cpu_load_info = (processor_cpu_load_info_t) info; + if (precise_user_kernel_time) { + cpu_load_info->cpu_ticks[CPU_STATE_USER] = + (uint32_t)(timer_grab(&PROCESSOR_DATA(processor, user_state)) / hz_tick_interval); + cpu_load_info->cpu_ticks[CPU_STATE_SYSTEM] = + (uint32_t)(timer_grab(&PROCESSOR_DATA(processor, system_state)) / hz_tick_interval); + } else { + uint64_t tval = timer_grab(&PROCESSOR_DATA(processor, user_state)) + + timer_grab(&PROCESSOR_DATA(processor, system_state)); + + cpu_load_info->cpu_ticks[CPU_STATE_USER] = (uint32_t)(tval / hz_tick_interval); + cpu_load_info->cpu_ticks[CPU_STATE_SYSTEM] = 0; + } + + idle_state = &PROCESSOR_DATA(processor, idle_state); + idle_temp = *idle_state; + + if (PROCESSOR_DATA(processor, current_state) != idle_state || + timer_grab(&idle_temp) != timer_grab(idle_state)) { + cpu_load_info->cpu_ticks[CPU_STATE_IDLE] = + (uint32_t)(timer_grab(&PROCESSOR_DATA(processor, idle_state)) / hz_tick_interval); + } else { + timer_advance(&idle_temp, mach_absolute_time() - idle_temp.tstamp); + + cpu_load_info->cpu_ticks[CPU_STATE_IDLE] = + (uint32_t)(timer_grab(&idle_temp) / hz_tick_interval); + } - cpu_load_info = (processor_cpu_load_info_t) info; - for (i=0;icpu_ticks[i] = machine_slot[slot_num].cpu_ticks[i]; + cpu_load_info->cpu_ticks[CPU_STATE_NICE] = 0; *count = PROCESSOR_CPU_LOAD_INFO_COUNT; *host = &realhost; - return(KERN_SUCCESS); - } + + return (KERN_SUCCESS); + } + default: - { - kr=cpu_info(flavor, slot_num, info, count); - if (kr == KERN_SUCCESS) - *host = &realhost; - return(kr); - } + result = cpu_info(flavor, cpu_id, info, count); + if (result == KERN_SUCCESS) + *host = &realhost; + + return (result); } } kern_return_t processor_start( - processor_t processor) + processor_t processor) { - int state; - spl_t s; - kern_return_t kr; + processor_set_t pset; + thread_t thread; + kern_return_t result; + spl_t s; - if (processor == PROCESSOR_NULL) - return(KERN_INVALID_ARGUMENT); + if (processor == PROCESSOR_NULL || processor->processor_set == PROCESSOR_SET_NULL) + return (KERN_INVALID_ARGUMENT); if (processor == master_processor) { - thread_bind(current_thread(), processor); + processor_t prev; + + prev = thread_bind(processor); thread_block(THREAD_CONTINUE_NULL); - kr = cpu_start(processor->slot_num); - thread_bind(current_thread(), PROCESSOR_NULL); - return(kr); + result = cpu_start(processor->cpu_id); + + thread_bind(prev); + + return (result); } s = splsched(); - processor_lock(processor); - - state = processor->state; - if (state != PROCESSOR_OFF_LINE) { - processor_unlock(processor); + pset = processor->processor_set; + pset_lock(pset); + if (processor->state != PROCESSOR_OFF_LINE) { + pset_unlock(pset); splx(s); - return(KERN_FAILURE); + + return (KERN_FAILURE); } + processor->state = PROCESSOR_START; - processor_unlock(processor); + pset_unlock(pset); splx(s); - if (processor->next_thread == THREAD_NULL) { - thread_t thread; - extern void start_cpu_thread(void); - - thread = kernel_thread_with_priority( - kernel_task, MAXPRI_KERNEL, - start_cpu_thread, TRUE, FALSE); + /* + * Create the idle processor thread. + */ + if (processor->idle_thread == THREAD_NULL) { + result = idle_thread_create(processor); + if (result != KERN_SUCCESS) { + s = splsched(); + pset_lock(pset); + processor->state = PROCESSOR_OFF_LINE; + pset_unlock(pset); + splx(s); + + return (result); + } + } + + /* + * If there is no active thread, the processor + * has never been started. Create a dedicated + * start up thread. + */ + if ( processor->active_thread == THREAD_NULL && + processor->next_thread == THREAD_NULL ) { + result = kernel_thread_create((thread_continue_t)processor_start_thread, NULL, MAXPRI_KERNEL, &thread); + if (result != KERN_SUCCESS) { + s = splsched(); + pset_lock(pset); + processor->state = PROCESSOR_OFF_LINE; + pset_unlock(pset); + splx(s); + + return (result); + } s = splsched(); thread_lock(thread); - thread_bind_locked(thread, processor); - thread_go_locked(thread, THREAD_AWAKENED); - (void)rem_runq(thread); + thread->bound_processor = processor; processor->next_thread = thread; + thread->state = TH_RUN; thread_unlock(thread); splx(s); + + thread_deallocate(thread); } - kr = cpu_start(processor->slot_num); + if (processor->processor_self == IP_NULL) + ipc_processor_init(processor); - if (kr != KERN_SUCCESS) { + result = cpu_start(processor->cpu_id); + if (result != KERN_SUCCESS) { s = splsched(); - processor_lock(processor); + pset_lock(pset); processor->state = PROCESSOR_OFF_LINE; - processor_unlock(processor); + pset_unlock(pset); splx(s); + + return (result); } - return(kr); + ipc_processor_enable(processor); + + return (KERN_SUCCESS); } kern_return_t @@ -545,49 +506,22 @@ processor_control( if (processor == PROCESSOR_NULL) return(KERN_INVALID_ARGUMENT); - return(cpu_control(processor->slot_num, info, count)); -} - -/* - * Precalculate the appropriate timesharing quanta based on load. The - * index into machine_quanta is the number of threads on the - * processor set queue. It is limited to the number of processors in - * the set. - */ - -void -pset_quanta_set( - processor_set_t pset) -{ - register int i, count = pset->processor_count; - - for (i = 1; i <= count; i++) - pset->machine_quanta[i] = (count + (i / 2)) / i; - - pset->machine_quanta[0] = pset->machine_quanta[1]; - - pset_quanta_update(pset); + return(cpu_control(processor->cpu_id, info, count)); } kern_return_t processor_set_create( - host_t host, - processor_set_t *new_set, - processor_set_t *new_name) + __unused host_t host, + __unused processor_set_t *new_set, + __unused processor_set_t *new_name) { -#ifdef lint - host++; new_set++; new_name++; -#endif /* lint */ return(KERN_FAILURE); } kern_return_t processor_set_destroy( - processor_set_t pset) + __unused processor_set_t pset) { -#ifdef lint - pset++; -#endif /* lint */ return(KERN_FAILURE); } @@ -596,14 +530,17 @@ processor_get_assignment( processor_t processor, processor_set_t *pset) { - int state; + int state; + + if (processor == PROCESSOR_NULL) + return(KERN_INVALID_ARGUMENT); state = processor->state; if (state == PROCESSOR_SHUTDOWN || state == PROCESSOR_OFF_LINE) return(KERN_FAILURE); - *pset = processor->processor_set; - pset_reference(*pset); + *pset = &pset0; + return(KERN_SUCCESS); } @@ -625,7 +562,7 @@ processor_set_info( return(KERN_FAILURE); basic_info = (processor_set_basic_info_t) info; - basic_info->processor_count = pset->processor_count; + basic_info->processor_count = processor_avail_count; basic_info->default_policy = POLICY_TIMESHARE; *count = PROCESSOR_SET_BASIC_INFO_COUNT; @@ -679,7 +616,7 @@ processor_set_info( return(KERN_FAILURE); ts_limit = (policy_timeshare_limit_t) info; - ts_limit->max_priority = MAXPRI_STANDARD; + ts_limit->max_priority = MAXPRI_KERNEL; *count = POLICY_TIMESHARE_LIMIT_COUNT; *host = &realhost; @@ -692,7 +629,7 @@ processor_set_info( return(KERN_FAILURE); fifo_limit = (policy_fifo_limit_t) info; - fifo_limit->max_priority = MAXPRI_STANDARD; + fifo_limit->max_priority = MAXPRI_KERNEL; *count = POLICY_FIFO_LIMIT_COUNT; *host = &realhost; @@ -705,7 +642,7 @@ processor_set_info( return(KERN_FAILURE); rr_limit = (policy_rr_limit_t) info; - rr_limit->max_priority = MAXPRI_STANDARD; + rr_limit->max_priority = MAXPRI_KERNEL; *count = POLICY_RR_LIMIT_COUNT; *host = &realhost; @@ -742,29 +679,28 @@ processor_set_statistics( processor_set_info_t info, mach_msg_type_number_t *count) { - if (pset == PROCESSOR_SET_NULL) - return (KERN_INVALID_PROCESSOR_SET); + if (pset == PROCESSOR_SET_NULL || pset != &pset0) + return (KERN_INVALID_PROCESSOR_SET); - if (flavor == PROCESSOR_SET_LOAD_INFO) { - register processor_set_load_info_t load_info; + if (flavor == PROCESSOR_SET_LOAD_INFO) { + register processor_set_load_info_t load_info; - if (*count < PROCESSOR_SET_LOAD_INFO_COUNT) - return(KERN_FAILURE); + if (*count < PROCESSOR_SET_LOAD_INFO_COUNT) + return(KERN_FAILURE); - load_info = (processor_set_load_info_t) info; + load_info = (processor_set_load_info_t) info; - pset_lock(pset); - load_info->task_count = pset->task_count; - load_info->thread_count = pset->thread_count; - load_info->mach_factor = pset->mach_factor; - load_info->load_average = pset->load_average; - pset_unlock(pset); + load_info->mach_factor = sched_mach_factor; + load_info->load_average = sched_load_average; - *count = PROCESSOR_SET_LOAD_INFO_COUNT; - return(KERN_SUCCESS); - } + load_info->task_count = tasks_count; + load_info->thread_count = threads_count; - return(KERN_INVALID_ARGUMENT); + *count = PROCESSOR_SET_LOAD_INFO_COUNT; + return(KERN_SUCCESS); + } + + return(KERN_INVALID_ARGUMENT); } /* @@ -776,9 +712,9 @@ processor_set_statistics( */ kern_return_t processor_set_max_priority( - processor_set_t pset, - int max_priority, - boolean_t change_threads) + __unused processor_set_t pset, + __unused int max_priority, + __unused boolean_t change_threads) { return (KERN_INVALID_ARGUMENT); } @@ -791,8 +727,8 @@ processor_set_max_priority( kern_return_t processor_set_policy_enable( - processor_set_t pset, - int policy) + __unused processor_set_t pset, + __unused int policy) { return (KERN_INVALID_ARGUMENT); } @@ -805,9 +741,9 @@ processor_set_policy_enable( */ kern_return_t processor_set_policy_disable( - processor_set_t pset, - int policy, - boolean_t change_threads) + __unused processor_set_t pset, + __unused int policy, + __unused boolean_t change_threads) { return (KERN_INVALID_ARGUMENT); } @@ -822,42 +758,40 @@ processor_set_policy_disable( */ kern_return_t processor_set_things( - processor_set_t pset, - mach_port_t **thing_list, + processor_set_t pset, + mach_port_t **thing_list, mach_msg_type_number_t *count, - int type) + int type) { unsigned int actual; /* this many things */ - int i; + unsigned int maxthings; + unsigned int i; vm_size_t size, size_needed; - vm_offset_t addr; + void *addr; - if (pset == PROCESSOR_SET_NULL) - return KERN_INVALID_ARGUMENT; + if (pset == PROCESSOR_SET_NULL || pset != &pset0) + return (KERN_INVALID_ARGUMENT); - size = 0; addr = 0; + size = 0; + addr = NULL; for (;;) { - pset_lock(pset); - if (!pset->active) { - pset_unlock(pset); - return KERN_FAILURE; - } + lck_mtx_lock(&tasks_threads_lock); if (type == THING_TASK) - actual = pset->task_count; + maxthings = tasks_count; else - actual = pset->thread_count; + maxthings = threads_count; /* do we have the memory we need? */ - size_needed = actual * sizeof(mach_port_t); + size_needed = maxthings * sizeof (mach_port_t); if (size_needed <= size) break; - /* unlock the pset and allocate more memory */ - pset_unlock(pset); + /* unlock and allocate more memory */ + lck_mtx_unlock(&tasks_threads_lock); if (size != 0) kfree(addr, size); @@ -867,127 +801,125 @@ processor_set_things( addr = kalloc(size); if (addr == 0) - return KERN_RESOURCE_SHORTAGE; + return (KERN_RESOURCE_SHORTAGE); } - /* OK, have memory and the processor_set is locked & active */ + /* OK, have memory and the list locked */ + actual = 0; switch (type) { - case THING_TASK: { - task_t *tasks = (task_t *) addr; - task_t task; - - for (i = 0, task = (task_t) queue_first(&pset->tasks); - !queue_end(&pset->tasks, (queue_entry_t) task); - task = (task_t) queue_next(&task->pset_tasks)) { - - task_lock(task); - if (task->ref_count > 0) { - /* take ref for convert_task_to_port */ - task_reference_locked(task); - tasks[i++] = task; + + case THING_TASK: { + task_t task, *task_list = (task_t *)addr; + + for (task = (task_t)queue_first(&tasks); + !queue_end(&tasks, (queue_entry_t)task); + task = (task_t)queue_next(&task->tasks)) { +#if defined(SECURE_KERNEL) + if (task != kernel_task) { +#endif + task_reference_internal(task); + task_list[actual++] = task; +#if defined(SECURE_KERNEL) } - task_unlock(task); +#endif } + break; - } - - case THING_THREAD: { - thread_act_t *thr_acts = (thread_act_t *) addr; - thread_t thread; - thread_act_t thr_act; - - for (i = 0, thread = (thread_t) queue_first(&pset->threads); - !queue_end(&pset->threads, (queue_entry_t)thread); - thread = (thread_t) queue_next(&thread->pset_threads)) { - - thr_act = thread_lock_act(thread); - if (thr_act && thr_act->ref_count > 0) { - /* take ref for convert_act_to_port */ - act_locked_act_reference(thr_act); - thr_acts[i++] = thr_act; - } - thread_unlock_act(thread); + } + + case THING_THREAD: { + thread_t thread, *thread_list = (thread_t *)addr; + + for (thread = (thread_t)queue_first(&threads); + !queue_end(&threads, (queue_entry_t)thread); + thread = (thread_t)queue_next(&thread->threads)) { + thread_reference_internal(thread); + thread_list[actual++] = thread; } + break; - } } - - /* can unlock processor set now that we have the task/thread refs */ - pset_unlock(pset); - if (i < actual) { - actual = i; - size_needed = actual * sizeof(mach_port_t); } - assert(i == actual); + + lck_mtx_unlock(&tasks_threads_lock); + + if (actual < maxthings) + size_needed = actual * sizeof (mach_port_t); if (actual == 0) { /* no things, so return null pointer and deallocate memory */ - *thing_list = 0; + *thing_list = NULL; *count = 0; if (size != 0) kfree(addr, size); - } else { + } + else { /* if we allocated too much, must copy */ if (size_needed < size) { - vm_offset_t newaddr; + void *newaddr; newaddr = kalloc(size_needed); if (newaddr == 0) { switch (type) { - case THING_TASK: { - task_t *tasks = (task_t *) addr; + + case THING_TASK: { + task_t *task_list = (task_t *)addr; for (i = 0; i < actual; i++) - task_deallocate(tasks[i]); + task_deallocate(task_list[i]); break; - } + } - case THING_THREAD: { - thread_act_t *acts = (thread_act_t *) addr; + case THING_THREAD: { + thread_t *thread_list = (thread_t *)addr; for (i = 0; i < actual; i++) - act_deallocate(acts[i]); + thread_deallocate(thread_list[i]); break; - } } + + } + kfree(addr, size); - return KERN_RESOURCE_SHORTAGE; + return (KERN_RESOURCE_SHORTAGE); } - bcopy((char *) addr, (char *) newaddr, size_needed); + bcopy((void *) addr, (void *) newaddr, size_needed); kfree(addr, size); addr = newaddr; } - *thing_list = (mach_port_t *) addr; + *thing_list = (mach_port_t *)addr; *count = actual; /* do the conversion that Mig should handle */ switch (type) { - case THING_TASK: { - task_t *tasks = (task_t *) addr; + + case THING_TASK: { + task_t *task_list = (task_t *)addr; for (i = 0; i < actual; i++) - (*thing_list)[i] = convert_task_to_port(tasks[i]); + (*thing_list)[i] = convert_task_to_port(task_list[i]); break; - } + } - case THING_THREAD: { - thread_act_t *thr_acts = (thread_act_t *) addr; + case THING_THREAD: { + thread_t *thread_list = (thread_t *)addr; for (i = 0; i < actual; i++) - (*thing_list)[i] = convert_act_to_port(thr_acts[i]); + (*thing_list)[i] = convert_thread_to_port(thread_list[i]); break; - } + } + } } - return(KERN_SUCCESS); + return (KERN_SUCCESS); } @@ -1010,48 +942,34 @@ processor_set_tasks( * * List all threads in the processor set. */ +#if defined(SECURE_KERNEL) kern_return_t processor_set_threads( - processor_set_t pset, - thread_array_t *thread_list, - mach_msg_type_number_t *count) + __unused processor_set_t pset, + __unused thread_array_t *thread_list, + __unused mach_msg_type_number_t *count) { - return(processor_set_things(pset, (mach_port_t **)thread_list, count, THING_THREAD)); + return KERN_FAILURE; } - -/* - * processor_set_base: - * - * Specify per-policy base priority for a processor set. Set processor - * set default policy to the given policy. This affects newly created - * and assigned threads. Optionally change existing ones. - */ +#elif defined(CONFIG_EMBEDDED) kern_return_t -processor_set_base( - processor_set_t pset, - policy_t policy, - policy_base_t base, - boolean_t change) +processor_set_threads( + __unused processor_set_t pset, + __unused thread_array_t *thread_list, + __unused mach_msg_type_number_t *count) { - return (KERN_INVALID_ARGUMENT); + return KERN_NOT_SUPPORTED; } - -/* - * processor_set_limit: - * - * Specify per-policy limits for a processor set. This affects - * newly created and assigned threads. Optionally change existing - * ones. - */ +#else kern_return_t -processor_set_limit( - processor_set_t pset, - policy_t policy, - policy_limit_t limit, - boolean_t change) +processor_set_threads( + processor_set_t pset, + thread_array_t *thread_list, + mach_msg_type_number_t *count) { - return (KERN_POLICY_LIMIT); + return(processor_set_things(pset, (mach_port_t **)thread_list, count, THING_THREAD)); } +#endif /* * processor_set_policy_control @@ -1062,11 +980,29 @@ processor_set_limit( */ kern_return_t processor_set_policy_control( - processor_set_t pset, - int flavor, - processor_set_info_t policy_info, - mach_msg_type_number_t count, - boolean_t change) + __unused processor_set_t pset, + __unused int flavor, + __unused processor_set_info_t policy_info, + __unused mach_msg_type_number_t count, + __unused boolean_t change) { return (KERN_INVALID_ARGUMENT); } + +#undef pset_deallocate +void pset_deallocate(processor_set_t pset); +void +pset_deallocate( +__unused processor_set_t pset) +{ + return; +} + +#undef pset_reference +void pset_reference(processor_set_t pset); +void +pset_reference( +__unused processor_set_t pset) +{ + return; +}