/*
- * 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@
*/
/*
- * processor.h: Processor and processor-set definitions.
+ * processor.h: Processor and processor-related definitions.
*/
#ifndef _KERN_PROCESSOR_H_
#define _KERN_PROCESSOR_H_
-/*
- * Data structures for managing processors and sets of processors.
- */
#include <mach/boolean.h>
#include <mach/kern_return.h>
#include <kern/kern_types.h>
-extern struct processor_set default_pset;
-extern processor_t master_processor;
+#include <sys/cdefs.h>
-#ifdef MACH_KERNEL_PRIVATE
-
-#include <cpus.h>
+#ifdef MACH_KERNEL_PRIVATE
#include <mach/mach_types.h>
+#include <kern/ast.h>
#include <kern/cpu_number.h>
#include <kern/lock.h>
#include <kern/queue.h>
#include <kern/sched.h>
+#include <kern/processor_data.h>
#include <machine/ast_types.h>
struct processor_set {
- struct run_queue runq; /* runq for this set */
+ queue_head_t active_queue; /* active processors */
queue_head_t idle_queue; /* idle processors */
- int idle_count; /* how many ? */
- decl_simple_lock_data(,idle_lock) /* lock for above */
- queue_head_t processors; /* all processors here */
- int processor_count;/* how many ? */
- decl_simple_lock_data(,processors_lock) /* lock for above */
- queue_head_t tasks; /* tasks assigned */
- int task_count; /* how many */
- queue_head_t threads; /* threads in this set */
- int thread_count; /* how many */
- int ref_count; /* structure ref count */
- boolean_t active; /* is pset in use */
- decl_mutex_data(, lock) /* lock for everything else */
+
+ processor_t low_pri, low_count;
+
+ int processor_count;
+
+ int cpu_set_low, cpu_set_hi;
+ int cpu_set_count;
+
+ decl_simple_lock_data(,sched_lock) /* lock for above */
+
struct ipc_port * pset_self; /* port for operations */
struct ipc_port * pset_name_self; /* port for information */
- int set_quanta; /* timeslice quanta for timesharing */
- int machine_quanta[NCPUS+1];
- integer_t mach_factor; /* mach_factor */
- integer_t load_average; /* load_average */
- long sched_load; /* load avg for scheduler */
+
+ processor_set_t pset_list; /* chain of associated psets */
+ pset_node_t node;
};
-struct processor {
- struct run_queue runq; /* local runq for this processor */
- queue_chain_t processor_queue;/* idle/assign/shutdown queue link */
- int state; /* See below */
- struct thread_shuttle
- *next_thread, /* next thread to run if dispatched */
- *idle_thread; /* this processor's idle thread. */
- timer_call_data_t quantum_timer; /* timer for quantum expiration */
- int slice_quanta; /* quanta before timeslice ends */
- uint64_t quantum_end; /* time when current quantum ends */
- uint64_t last_dispatch; /* time of last dispatch */
+extern struct processor_set pset0;
- processor_set_t processor_set; /* processor set I belong to */
- processor_set_t processor_set_next; /* set I will belong to */
- queue_chain_t processors; /* all processors in set */
- decl_simple_lock_data(,lock)
- struct ipc_port *processor_self;/* port for operations */
- int slot_num; /* machine-indep slot number */
-};
+struct pset_node {
+ processor_set_t psets; /* list of associated psets */
-extern struct processor processor_array[NCPUS];
+ pset_node_t nodes; /* list of associated subnodes */
+ pset_node_t node_list; /* chain of associated nodes */
-/*
- * NOTE: The processor->processor_set link is needed in one of the
- * scheduler's critical paths. [Figure out where to look for another
- * thread to run on this processor.] It is accessed without locking.
- * The following access protocol controls this field.
- *
- * Read from own processor - just read.
- * Read from another processor - lock processor structure during read.
- * Write from own processor - lock processor structure during write.
- * Write from another processor - NOT PERMITTED.
- *
- */
+ pset_node_t parent;
+};
-/*
- * Processor state locking:
- *
- * Values for the processor state are defined below. If the processor
- * is off-line or being shutdown, then it is only necessary to lock
- * the processor to change its state. Otherwise it is only necessary
- * to lock its processor set's idle_lock. Scheduler code will
- * typically lock only the idle_lock, but processor manipulation code
- * will often lock both.
- */
+extern struct pset_node pset_node0;
-#define PROCESSOR_OFF_LINE 0 /* Not in system */
-#define PROCESSOR_RUNNING 1 /* Running a normal thread */
-#define PROCESSOR_IDLE 2 /* idle */
-#define PROCESSOR_DISPATCHING 3 /* dispatching (idle -> running) */
-#define PROCESSOR_ASSIGN 4 /* Assignment is changing */
-#define PROCESSOR_SHUTDOWN 5 /* Being shutdown */
-#define PROCESSOR_START 6 /* Being start */
+extern queue_head_t tasks, threads;
+extern int tasks_count, threads_count;
+decl_lck_mtx_data(extern,tasks_threads_lock)
-/*
- * Use processor ptr array to find current processor's data structure.
- * This replaces a multiplication (index into processor_array) with
- * an array lookup and a memory reference. It also allows us to save
- * space if processor numbering gets too sparse.
- */
+struct processor_meta {
+ queue_head_t idle_queue;
+ processor_t primary;
+};
-extern processor_t processor_ptr[NCPUS];
+typedef struct processor_meta *processor_meta_t;
+#define PROCESSOR_META_NULL ((processor_meta_t) 0)
-#define cpu_to_processor(i) (processor_ptr[i])
+struct processor {
+ queue_chain_t processor_queue;/* idle/active queue link,
+ * MUST remain the first element */
+ int state; /* See below */
+ struct thread
+ *active_thread, /* thread running on processor */
+ *next_thread, /* next thread when dispatched */
+ *idle_thread; /* this processor's idle thread. */
-#define current_processor() (processor_ptr[cpu_number()])
-#define current_processor_set() (current_processor()->processor_set)
+ processor_set_t processor_set; /* assigned set */
-/* Compatibility -- will go away */
+ int current_pri; /* priority of current thread */
+ int cpu_id; /* platform numeric id */
-#define cpu_state(slot_num) (processor_ptr[slot_num]->state)
-#define cpu_idle(slot_num) (cpu_state(slot_num) == PROCESSOR_IDLE)
+ timer_call_data_t quantum_timer; /* timer for quantum expiration */
+ uint64_t quantum_end; /* time when current quantum ends */
+ uint64_t last_dispatch; /* time of last dispatch */
-/* Useful lock macros */
+ uint64_t deadline; /* current deadline */
+ int timeslice; /* quanta before timeslice ends */
-#define pset_lock(pset) mutex_lock(&(pset)->lock)
-#define pset_lock_try(pset) mutex_try(&(pset)->lock)
-#define pset_unlock(pset) mutex_unlock(&(pset)->lock)
+ struct run_queue runq; /* runq for this processor */
+ processor_meta_t processor_meta;
-#define processor_lock(pr) simple_lock(&(pr)->lock)
-#define processor_unlock(pr) simple_unlock(&(pr)->lock)
+ struct ipc_port * processor_self; /* port for operations */
+ processor_t processor_list; /* all existing processors */
+ processor_data_t processor_data; /* per-processor data */
+};
-extern void pset_sys_bootstrap(void);
+extern processor_t processor_list;
+extern unsigned int processor_count;
+decl_simple_lock_data(extern,processor_list_lock)
-/* Implemented by MD layer */
+extern uint32_t processor_avail_count;
-extern void cpu_up(
- int cpu);
+extern processor_t master_processor;
+
+/*
+ * Processor state is accessed by locking the scheduling lock
+ * for the assigned processor set.
+ */
+#define PROCESSOR_OFF_LINE 0 /* Not available */
+#define PROCESSOR_SHUTDOWN 1 /* Going off-line */
+#define PROCESSOR_START 2 /* Being started */
+#define PROCESSOR_INACTIVE 3 /* Inactive (unavailable) */
+#define PROCESSOR_IDLE 4 /* Idle (available) */
+#define PROCESSOR_DISPATCHING 5 /* Dispatching (idle -> active) */
+#define PROCESSOR_RUNNING 6 /* Normal execution */
+
+extern processor_t current_processor(void);
+
+extern processor_t cpu_to_processor(
+ int cpu);
+
+/* Lock macros */
+
+#define pset_lock(p) simple_lock(&(p)->sched_lock)
+#define pset_unlock(p) simple_unlock(&(p)->sched_lock)
+#define pset_lock_init(p) simple_lock_init(&(p)->sched_lock, 0)
+
+/* Update hints */
+
+#define pset_pri_hint(ps, p, pri) \
+MACRO_BEGIN \
+ if ((p) != (ps)->low_pri) { \
+ if ((pri) < (ps)->low_pri->current_pri) \
+ (ps)->low_pri = (p); \
+ else \
+ if ((ps)->low_pri->state < PROCESSOR_IDLE) \
+ (ps)->low_pri = (p); \
+ } \
+MACRO_END
+
+#define pset_count_hint(ps, p, cnt) \
+MACRO_BEGIN \
+ if ((p) != (ps)->low_count) { \
+ if ((cnt) < (ps)->low_count->runq.count) \
+ (ps)->low_count = (p); \
+ else \
+ if ((ps)->low_count->state < PROCESSOR_IDLE) \
+ (ps)->low_count = (p); \
+ } \
+MACRO_END
+
+extern void processor_bootstrap(void) __attribute__((section("__TEXT, initcode")));
+
+extern void processor_init(
+ processor_t processor,
+ int cpu_id,
+ processor_set_t processor_set) __attribute__((section("__TEXT, initcode")));
+
+extern void processor_meta_init(
+ processor_t processor,
+ processor_t primary);
extern kern_return_t processor_shutdown(
- processor_t processor);
+ processor_t processor);
-extern void pset_remove_processor(
- processor_set_t pset,
- processor_t processor);
+extern void processor_queue_shutdown(
+ processor_t processor);
-extern void pset_add_processor(
- processor_set_t pset,
- processor_t processor);
+extern processor_set_t processor_pset(
+ processor_t processor);
-extern void pset_remove_task(
- processor_set_t pset,
- task_t task);
+extern pset_node_t pset_node_root(void);
-extern void pset_add_task(
- processor_set_t pset,
- task_t task);
+extern processor_set_t pset_create(
+ pset_node_t node);
-extern void pset_remove_thread(
- processor_set_t pset,
- thread_t thread);
+extern void pset_init(
+ processor_set_t pset,
+ pset_node_t node) __attribute__((section("__TEXT, initcode")));
-extern void pset_add_thread(
- processor_set_t pset,
- thread_t thread);
+extern kern_return_t processor_info_count(
+ processor_flavor_t flavor,
+ mach_msg_type_number_t *count);
-extern void thread_change_psets(
- thread_t thread,
- processor_set_t old_pset,
- processor_set_t new_pset);
+#define pset_deallocate(x)
+#define pset_reference(x)
-extern void pset_deallocate(
- processor_set_t pset);
+extern void machine_run_count(
+ uint32_t count);
-extern void pset_reference(
- processor_set_t pset);
+extern boolean_t machine_processor_is_inactive(
+ processor_t processor);
-extern kern_return_t processor_assign(
- processor_t processor,
- processor_set_t new_pset,
- boolean_t wait);
+extern processor_t machine_choose_processor(
+ processor_set_t pset,
+ processor_t processor);
-extern kern_return_t processor_info_count(
- processor_flavor_t flavor,
- mach_msg_type_number_t *count);
-#endif /* MACH_KERNEL_PRIVATE */
+#else /* MACH_KERNEL_PRIVATE */
+
+__BEGIN_DECLS
+
+extern void pset_deallocate(
+ processor_set_t pset);
+
+extern void pset_reference(
+ processor_set_t pset);
-extern kern_return_t processor_start(
- processor_t processor);
+__END_DECLS
-extern kern_return_t processor_exit(
- processor_t processor);
+#endif /* MACH_KERNEL_PRIVATE */
#endif /* _KERN_PROCESSOR_H_ */