diff options
Diffstat (limited to 'kern')
80 files changed, 2707 insertions, 1502 deletions
@@ -64,7 +64,7 @@ static Act free_acts[ACT_STATIC_KLUDGE]; Act null_act; void -global_act_init() +global_act_init(void) { #ifndef ACT_STATIC_KLUDGE kmem_cache_init(&act_cache, "Act", sizeof(struct Act), 0, @@ -97,7 +97,6 @@ kern_return_t act_create(task_t task, vm_offset_t user_stack, struct Act **new_act) { Act *act; - int rc; #ifndef ACT_STATIC_KLUDGE act = (Act*)kmem_cache_alloc(&act_cache); @@ -258,7 +257,7 @@ void act_detach(Act *cur_act) so RPC entry paths need not check it. Locking: Act */ -void act_execute_returnhandlers() +void act_execute_returnhandlers(void) { Act *act = current_act(); @@ -1014,11 +1013,11 @@ act_set_special_port(Act *act, int which, ipc_port_t port) * Return thread's machine-dependent state. */ kern_return_t -act_get_state_immediate(act, flavor, old_state, old_state_count) - register Act *act; - int flavor; - void *old_state; /* pointer to OUT array */ - unsigned int *old_state_count; /*IN/OUT*/ +act_get_state_immediate( + Act *act, + int flavor, + void *old_state, /* pointer to OUT array */ + unsigned int *old_state_count) /*IN/OUT*/ { kern_return_t ret; @@ -1040,11 +1039,11 @@ act_get_state_immediate(act, flavor, old_state, old_state_count) * Change thread's machine-dependent state. */ kern_return_t -act_set_state_immediate(act, flavor, new_state, new_state_count) - register Act *act; - int flavor; - void *new_state; - unsigned int new_state_count; +act_set_state_immediate( + Act *act, + int flavor, + void *new_state, + unsigned int new_state_count) { kern_return_t ret; @@ -1062,7 +1061,7 @@ act_set_state_immediate(act, flavor, new_state, new_state_count) return act_set_state(act, flavor, new_state, new_state_count); } -void act_count() +void act_count(void) { int i; Act *act; @@ -1077,7 +1076,7 @@ void act_count() ACT_STATIC_KLUDGE-i, ACT_STATIC_KLUDGE, ACT_STATIC_KLUDGE-amin); } -dump_act(act) +void dump_act(act) Act *act; { act_count(); @@ -1098,8 +1097,7 @@ dump_act(act) #ifdef ACTWATCH Act * -get_next_act(sp) - int sp; +get_next_act(int sp) { static int i; Act *act; @@ -1115,6 +1113,6 @@ get_next_act(sp) return act; } } -#endif +#endif /* ACTWATCH */ #endif /* MIGRATING_THREADS */ @@ -40,8 +40,6 @@ #include <kern/refcount.h> #include <kern/queue.h> -#include "act.h"/*XXX*/ - struct task; struct thread; struct Act; @@ -176,7 +174,6 @@ kern_return_t act_terminate_task_locked(struct Act *act); /* Exported to thread.c */ extern Act null_act; -kern_return_t act_create_kernel(Act **out_act); /* Exported to machine-dependent activation code */ void act_execute_returnhandlers(void); @@ -192,4 +189,4 @@ kern_return_t act_machine_get_state(Act *inc, int flavor, int *tstate, unsigned #endif /* MIGRATING_THREADS */ -#endif _KERN_ACT_H_ +#endif /* _KERN_ACT_H_ */ diff --git a/kern/assert.h b/kern/assert.h index 2829728b..7b66d1b1 100644 --- a/kern/assert.h +++ b/kern/assert.h @@ -29,26 +29,21 @@ /* assert.h 4.2 85/01/21 */ -#include <kern/macro_help.h> +#include <kern/macros.h> #ifndef NDEBUG #define MACH_ASSERT 1 #endif #if MACH_ASSERT -extern void Assert(char *exp, char *filename, int line) __attribute__ ((noreturn)); +extern void Assert(const char *exp, const char *filename, int line) __attribute__ ((noreturn)); #define assert(ex) \ -MACRO_BEGIN \ - if (!(ex)) \ - Assert(#ex, __FILE__, __LINE__); \ -MACRO_END - -#ifdef lint -#define assert_static(x) -#else /* lint */ + ((ex) \ + ? (void) (0) \ + : Assert (#ex, __FILE__, __LINE__)) + #define assert_static(x) assert(x) -#endif /* lint */ #else /* MACH_ASSERT */ #define assert(ex) @@ -56,10 +56,10 @@ volatile ast_t need_ast[NCPUS]; void -ast_init() +ast_init(void) { #ifndef MACHINE_AST - register int i; + int i; for (i=0; i<NCPUS; i++) need_ast[i] = 0; @@ -69,8 +69,8 @@ ast_init() void ast_taken(void) { - register thread_t self = current_thread(); - register ast_t reasons; + thread_t self = current_thread(); + ast_t reasons; /* * Interrupts are still disabled. @@ -114,12 +114,12 @@ ast_taken(void) } void -ast_check() +ast_check(void) { - register int mycpu = cpu_number(); - register processor_t myprocessor; - register thread_t thread = current_thread(); - register run_queue_t rq; + int mycpu = cpu_number(); + processor_t myprocessor; + thread_t thread = current_thread(); + run_queue_t rq; spl_t s = splsched(); /* @@ -190,7 +190,7 @@ ast_check() #endif /* MACH_FIXPRI */ rq = &(myprocessor->processor_set->runq); if (!(myprocessor->first_quantum) && (rq->count > 0)) { - register queue_t q; + queue_t q; /* * This is not the first quantum, and there may * be something in the processor_set runq. @@ -198,7 +198,7 @@ ast_check() */ q = rq->runq + *(volatile int *)&rq->low; if (queue_empty(q)) { - register int i; + int i; /* * Need to recheck and possibly update hint. @@ -41,7 +41,7 @@ */ #include "cpu_number.h" -#include <kern/macro_help.h> +#include <kern/macros.h> #include <machine/ast.h> /* diff --git a/kern/boot_script.c b/kern/boot_script.c index b2e9393b..b245d1d8 100644 --- a/kern/boot_script.c +++ b/kern/boot_script.c @@ -76,14 +76,14 @@ create_task (struct cmd *cmd, long *val) /* Resume a task. */ static int -resume_task (struct cmd *cmd, long *val) +resume_task (struct cmd *cmd, const long *val) { return boot_script_task_resume (cmd); } /* Resume a task when the user hits return. */ static int -prompt_resume_task (struct cmd *cmd, long *val) +prompt_resume_task (struct cmd *cmd, const long *val) { return boot_script_prompt_task_resume (cmd); } @@ -485,7 +485,7 @@ boot_script_parse_line (void *hook, char *cmdline) /* Execute commands previously parsed. */ int -boot_script_exec () +boot_script_exec (void) { int cmd_index; diff --git a/kern/boot_script.h b/kern/boot_script.h index c5ad6732..c007d777 100644 --- a/kern/boot_script.h +++ b/kern/boot_script.h @@ -69,10 +69,6 @@ int boot_script_exec_cmd (void *hook, task_t task, char *path, int argc, char **argv, char *strings, int stringlen); -/* The user must define this function. Load the contents of FILE - into a fresh anonymous memory object and return the memory object port. */ -mach_port_t boot_script_read_file (const char *file); - /* The user must define this functions to perform the corresponding Mach task manipulations. */ int boot_script_task_create (struct cmd *); /* task_create + task_suspend */ diff --git a/kern/bootstrap.c b/kern/bootstrap.c index 4a39f26a..0a8dcedb 100644 --- a/kern/bootstrap.c +++ b/kern/bootstrap.c @@ -37,6 +37,7 @@ #include <mach/message.h> #include <machine/locore.h> #include <machine/vm_param.h> +#include <machine/pcb.h> #include <ipc/ipc_port.h> #include <ipc/mach_port.h> #include <kern/debug.h> @@ -86,8 +87,8 @@ static mach_port_t boot_host_port; /* local name */ extern char *kernel_cmdline; -static void user_bootstrap(); /* forward */ -static void user_bootstrap_compat(); /* forward */ +static void user_bootstrap(void); /* forward */ +static void user_bootstrap_compat(void); /* forward */ static void bootstrap_exec_compat(void *exec_data); /* forward */ static void get_compat_strings(char *flags_str, char *root_str); /* forward */ @@ -111,7 +112,7 @@ task_insert_send_right( return name; } -void bootstrap_create() +void bootstrap_create(void) { int compat; int n = 0; @@ -165,18 +166,18 @@ void bootstrap_create() } else { - int i, losers, maxlen; + int i, losers; /* Initialize boot script variables. We leak these send rights. */ losers = boot_script_set_variable ("host-port", VAL_PORT, - (long)ipc_port_make_send(realhost.host_priv_self)); + (long) realhost.host_priv_self); if (losers) panic ("cannot set boot-script variable host-port: %s", boot_script_error_string (losers)); losers = boot_script_set_variable ("device-port", VAL_PORT, - (long) ipc_port_make_send(master_device_port)); + (long) master_device_port); if (losers) panic ("cannot set boot-script variable device-port: %s", boot_script_error_string (losers)); @@ -256,15 +257,11 @@ void bootstrap_create() } #endif - maxlen = 0; for (i = 0; i < boot_info.mods_count; ++i) { int err; char *line = (char*)phystokv(bmods[i].string); - int len = strlen (line) + 1; - if (len > maxlen) - maxlen = len; - printf ("\rmodule %d: %*s", i, -maxlen, line); + printf ("module %d: %s\n", i, line); err = boot_script_parse_line (&bmods[i], line); if (err) { @@ -272,7 +269,7 @@ void bootstrap_create() ++losers; } } - printf ("\r%d multiboot modules %*s", i, -maxlen, ""); + printf ("%d multiboot modules\n", i); if (losers) panic ("%d of %d boot script commands could not be parsed", losers, boot_info.mods_count); @@ -334,7 +331,7 @@ itoa( vm_size_t num) { char buf[sizeof(vm_size_t)*2+3]; - register char *np; + char *np; np = buf + sizeof(buf); *--np = 0; @@ -354,7 +351,7 @@ itoa( */ static void get_compat_strings(char *flags_str, char *root_str) { - register char *ip, *cp; + char *ip, *cp; strcpy (root_str, "UNKNOWN"); @@ -535,16 +532,12 @@ static void copy_bootstrap(void *e, exec_info_t *boot_exec_info) /* * Allocate the stack, and build the argument list. */ -extern vm_offset_t user_stack_low(); -extern vm_offset_t set_user_regs(); - static void build_args_and_stack(struct exec_info *boot_exec_info, char **argv, char **envp) { vm_offset_t stack_base; vm_size_t stack_size; - register char * arg_ptr; int arg_count, envc; int arg_len; @@ -606,7 +599,7 @@ build_args_and_stack(struct exec_info *boot_exec_info, /* * first the argument count */ - (void) copyout((char *)&arg_count, + (void) copyout(&arg_count, arg_pos, sizeof(integer_t)); arg_pos += sizeof(integer_t); @@ -619,7 +612,7 @@ build_args_and_stack(struct exec_info *boot_exec_info, arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */ /* set string pointer */ - (void) copyout((char *)&string_pos, + (void) copyout(&string_pos, arg_pos, sizeof (char *)); arg_pos += sizeof(char *); @@ -632,7 +625,7 @@ build_args_and_stack(struct exec_info *boot_exec_info, /* * Null terminator for argv. */ - (void) copyout((char *)&zero, arg_pos, sizeof(char *)); + (void) copyout(&zero, arg_pos, sizeof(char *)); arg_pos += sizeof(char *); /* @@ -643,7 +636,7 @@ build_args_and_stack(struct exec_info *boot_exec_info, arg_item_len = strlen(arg_ptr) + 1; /* include trailing 0 */ /* set string pointer */ - (void) copyout((char *)&string_pos, + (void) copyout(&string_pos, arg_pos, sizeof (char *)); arg_pos += sizeof(char *); @@ -656,12 +649,12 @@ build_args_and_stack(struct exec_info *boot_exec_info, /* * Null terminator for envp. */ - (void) copyout((char *)&zero, arg_pos, sizeof(char *)); + (void) copyout(&zero, arg_pos, sizeof(char *)); } static void -user_bootstrap_compat() +user_bootstrap_compat(void) { exec_info_t boot_exec_info; @@ -748,7 +741,8 @@ boot_script_exec_cmd (void *hook, task_t task, char *path, int argc, assert(err == 0); thread->saved.other = &info; thread_start (thread, user_bootstrap); - thread_resume (thread); + err = thread_resume (thread); + assert(err == 0); /* We need to synchronize with the new thread and block this main thread until it has finished referring to our local state. */ @@ -757,13 +751,14 @@ boot_script_exec_cmd (void *hook, task_t task, char *path, int argc, thread_sleep ((event_t) &info, simple_lock_addr(info.lock), FALSE); simple_lock (&info.lock); } + simple_unlock (&info.lock); printf ("\n"); } return 0; } -static void user_bootstrap() +static void user_bootstrap(void) { struct user_bootstrap_info *info = current_thread()->saved.other; exec_info_t boot_exec_info; @@ -791,6 +786,7 @@ static void user_bootstrap() simple_lock (&info->lock); assert (!info->done); info->done = 1; + simple_unlock (&info->lock); thread_wakeup ((event_t) info); /* @@ -823,6 +819,7 @@ boot_script_task_create (struct cmd *cmd) printf("boot_script_task_create failed with %x\n", rc); return BOOT_SCRIPT_MACH_ERROR; } + task_set_name(cmd->task, cmd->path); return 0; } @@ -860,7 +857,8 @@ boot_script_free_task (task_t task, int aborting) int boot_script_insert_right (struct cmd *cmd, mach_port_t port, mach_port_t *name) { - *name = task_insert_send_right (cmd->task, (ipc_port_t)port); + *name = task_insert_send_right (cmd->task, + ipc_port_make_send((ipc_port_t) port)); return 0; } diff --git a/kern/bootstrap.h b/kern/bootstrap.h new file mode 100644 index 00000000..b8ed8d9f --- /dev/null +++ b/kern/bootstrap.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Free Software Foundation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _KERN_BOOTSTRAP_H_ +#define _KERN_BOOTSTRAP_H_ + +extern void bootstrap_create(void); + +#endif /* _KERN_BOOTSTRAP_H_ */ diff --git a/kern/counters.c b/kern/counters.c index a9d450e1..0a0665bf 100644 --- a/kern/counters.c +++ b/kern/counters.c @@ -32,13 +32,12 @@ * This makes them easier to examine with ddb. */ +#if MACH_COUNTERS mach_counter_t c_thread_invoke_hits = 0; mach_counter_t c_thread_invoke_misses = 0; mach_counter_t c_thread_invoke_csw = 0; mach_counter_t c_thread_handoff_hits = 0; mach_counter_t c_thread_handoff_misses = 0; - -#if MACH_COUNTERS mach_counter_t c_threads_current = 0; mach_counter_t c_threads_max = 0; mach_counter_t c_threads_min = 0; @@ -47,6 +46,9 @@ mach_counter_t c_stacks_current = 0; mach_counter_t c_stacks_max = 0; mach_counter_t c_stacks_min = 0; mach_counter_t c_stacks_total = 0; +mach_counter_t c_stack_alloc_hits = 0; +mach_counter_t c_stack_alloc_misses = 0; +mach_counter_t c_stack_alloc_max = 0; mach_counter_t c_clock_ticks = 0; mach_counter_t c_ipc_mqueue_send_block = 0; mach_counter_t c_ipc_mqueue_receive_block_user = 0; diff --git a/kern/counters.h b/kern/counters.h index 474c6a29..aa1e739b 100644 --- a/kern/counters.h +++ b/kern/counters.h @@ -55,13 +55,12 @@ typedef unsigned int mach_counter_t; +#if MACH_COUNTERS extern mach_counter_t c_thread_invoke_hits; extern mach_counter_t c_thread_invoke_misses; extern mach_counter_t c_thread_invoke_csw; extern mach_counter_t c_thread_handoff_hits; extern mach_counter_t c_thread_handoff_misses; - -#if MACH_COUNTERS extern mach_counter_t c_threads_current; extern mach_counter_t c_threads_max; extern mach_counter_t c_threads_min; @@ -70,6 +69,9 @@ extern mach_counter_t c_stacks_current; extern mach_counter_t c_stacks_max; extern mach_counter_t c_stacks_min; extern mach_counter_t c_stacks_total; +extern mach_counter_t c_stack_alloc_hits; +extern mach_counter_t c_stack_alloc_misses; +extern mach_counter_t c_stack_alloc_max; extern mach_counter_t c_clock_ticks; extern mach_counter_t c_ipc_mqueue_send_block; extern mach_counter_t c_ipc_mqueue_receive_block_user; diff --git a/kern/debug.c b/kern/debug.c index 8a04f1db..faa03565 100644 --- a/kern/debug.c +++ b/kern/debug.c @@ -38,11 +38,7 @@ #include <machine/loose_ends.h> #include <machine/model_dep.h> -extern void cnputc(); - -#if MACH_KDB -extern int db_breakpoints_inserted; -#endif +#include <device/cons.h> #if NCPUS>1 simple_lock_data_t Assert_print_lock; /* uninited, we take our chances */ @@ -55,7 +51,7 @@ do_cnputc(char c, vm_offset_t offset) } void -Assert(char *exp, char *file, int line) +Assert(const char *exp, const char *file, int line) { #if NCPUS > 1 simple_lock(&Assert_print_lock); @@ -67,14 +63,11 @@ Assert(char *exp, char *file, int line) exp, file, line); #endif -#if MACH_KDB - if (db_breakpoints_inserted) -#endif Debugger("assertion failure"); } void SoftDebugger(message) - char * message; + const char *message; { printf("Debugger invoked: %s\n", message); @@ -96,7 +89,7 @@ void SoftDebugger(message) asm("ta 0x81"); #endif /* sun4 */ -#if defined(mips ) || defined(luna88k) || defined(i860) || defined(alpha) +#if defined(mips ) || defined(i860) || defined(alpha) gimmeabreak(); #endif @@ -106,7 +99,7 @@ void SoftDebugger(message) } void Debugger(message) - char * message; + const char *message; { #if !MACH_KDB panic("Debugger invoked, but there isn't one!"); @@ -201,14 +194,12 @@ log(int level, const char *fmt, ...) { va_list listp; -#ifdef lint - level++; -#endif va_start(listp, fmt); _doprnt(fmt, listp, do_cnputc, 0, 0); va_end(listp); } +/* GCC references this for stack protection. */ unsigned char __stack_chk_guard [ sizeof (vm_offset_t) ] = { [ sizeof (vm_offset_t) - 3 ] = '\r', diff --git a/kern/debug.h b/kern/debug.h index e429bdd1..6c8977b8 100644 --- a/kern/debug.h +++ b/kern/debug.h @@ -62,7 +62,7 @@ extern void log (int level, const char *fmt, ...); extern void panic_init(void); extern void panic (const char *s, ...) __attribute__ ((noreturn)); -extern void SoftDebugger (char *message); -extern void Debugger (char *message) __attribute__ ((noreturn)); +extern void SoftDebugger (const char *message); +extern void Debugger (const char *message) __attribute__ ((noreturn)); #endif /* _mach_debug__debug_ */ diff --git a/kern/elf-load.c b/kern/elf-load.c index 1d103d3c..441276ef 100644 --- a/kern/elf-load.c +++ b/kern/elf-load.c @@ -80,6 +80,8 @@ int exec_load(exec_read_func_t *read, exec_read_exec_func_t *read_exec, result = (*read_exec)(handle, ph->p_offset, ph->p_filesz, ph->p_vaddr, ph->p_memsz, type); + if (result) + return result; } } diff --git a/kern/eventcount.c b/kern/eventcount.c index 6fcebff5..a9d7bd41 100644 --- a/kern/eventcount.c +++ b/kern/eventcount.c @@ -53,13 +53,6 @@ #include <kern/eventcount.h> - -#if NCPUS <= 1 -void simpler_thread_setrun( - thread_t th, - boolean_t may_preempt); /* forward */ -#endif - #define MAX_EVCS 10 /* xxx for now */ evc_t all_eventcounters[MAX_EVCS]; @@ -105,7 +98,7 @@ evc_destroy(evc_t ev) * Thread termination. * HORRIBLE. This stuff needs to be fixed. */ -void evc_notify_abort(thread_t thread) +void evc_notify_abort(const thread_t thread) { int i; evc_t ev; @@ -130,7 +123,7 @@ void evc_notify_abort(thread_t thread) * Just so that we return success, and give * up the stack while blocked */ -static void +static void __attribute__((noreturn)) evc_continue(void) { thread_syscall_return(KERN_SUCCESS); @@ -235,8 +228,8 @@ kern_return_t evc_wait_clear(natural_t ev_id) void evc_signal(evc_t ev) { - register volatile thread_t thread; - register int state; + volatile thread_t thread; + int state; spl_t s; if (ev->sanity != ev) return; @@ -325,8 +318,8 @@ simpler_thread_setrun( thread_t th, boolean_t may_preempt) { - register struct run_queue *rq; - register int whichq; + struct run_queue *rq; + int whichq; /* * XXX should replace queue with a boolean in this case. @@ -347,7 +340,7 @@ simpler_thread_setrun( whichq = (th)->sched_pri; simple_lock(&(rq)->lock); /* lock the run queue */ - enqueue_head(&(rq)->runq[whichq], (queue_entry_t) (th)); + enqueue_head(&(rq)->runq[whichq], &((th)->links)); if (whichq < (rq)->low || (rq)->count == 0) (rq)->low = whichq; /* minimize */ diff --git a/kern/eventcount.h b/kern/eventcount.h index 6872a347..7cc82207 100644 --- a/kern/eventcount.h +++ b/kern/eventcount.h @@ -53,7 +53,12 @@ extern void evc_init(evc_t ev), /* kernel and user visible */ extern kern_return_t evc_wait(natural_t ev_id); +extern kern_return_t evc_wait_clear(natural_t ev_id); -extern void evc_notify_abort (thread_t thread); +#if NCPUS <= 1 +void simpler_thread_setrun( + thread_t th, + boolean_t may_preempt); +#endif #endif /* _KERN_EVENTCOUNT_H_ */ diff --git a/kern/exception.c b/kern/exception.c index 453a0758..6cb3bfbf 100644 --- a/kern/exception.c +++ b/kern/exception.c @@ -47,23 +47,13 @@ #include <kern/processor.h> #include <kern/sched.h> #include <kern/sched_prim.h> +#include <kern/exception.h> +#include <kern/macros.h> #include <mach/machine/vm_types.h> - - -extern void exception() __attribute__ ((noreturn)); -extern void exception_try_task() __attribute__ ((noreturn)); -extern void exception_no_server() __attribute__ ((noreturn)); - -extern void exception_raise() __attribute__ ((noreturn)); -extern kern_return_t exception_parse_reply(); -extern void exception_raise_continue() __attribute__ ((noreturn)); -extern void exception_raise_continue_slow() __attribute__ ((noreturn)); -extern void exception_raise_continue_fast() __attribute__ ((noreturn)); - #if MACH_KDB -extern void thread_kdb_return(); -extern void db_printf(); +#include <machine/trap.h> +#include <ddb/db_output.h> boolean_t debug_user_with_kdb = FALSE; #endif /* MACH_KDB */ @@ -93,11 +83,13 @@ boolean_t debug_user_with_kdb = FALSE; */ void -exception(_exception, code, subcode) - integer_t _exception, code, subcode; +exception( + integer_t _exception, + integer_t code, + integer_t subcode) { - register ipc_thread_t self = current_thread(); - register ipc_port_t exc_port; + ipc_thread_t self = current_thread(); + ipc_port_t exc_port; if (_exception == KERN_SUCCESS) panic("exception"); @@ -163,12 +155,14 @@ exception(_exception, code, subcode) */ void -exception_try_task(_exception, code, subcode) - integer_t _exception, code, subcode; +exception_try_task( + integer_t _exception, + integer_t code, + integer_t subcode) { ipc_thread_t self = current_thread(); - register task_t task = self->task; - register ipc_port_t exc_port; + task_t task = self->task; + ipc_port_t exc_port; /* * Optimized version of retrieve_task_exception. @@ -228,9 +222,9 @@ exception_try_task(_exception, code, subcode) */ void -exception_no_server() +exception_no_server(void) { - register ipc_thread_t self = current_thread(); + ipc_thread_t self = current_thread(); /* * If this thread is being terminated, cooperate. @@ -330,12 +324,13 @@ mach_msg_type_t exc_code_proto = { int exception_raise_misses = 0; void -exception_raise(dest_port, thread_port, task_port, - _exception, code, subcode) - ipc_port_t dest_port; - ipc_port_t thread_port; - ipc_port_t task_port; - integer_t _exception, code, subcode; +exception_raise( + ipc_port_t dest_port, + ipc_port_t thread_port, + ipc_port_t task_port, + integer_t _exception, + integer_t code, + integer_t subcode) { ipc_thread_t self = current_thread(); ipc_thread_t receiver; @@ -428,7 +423,7 @@ exception_raise(dest_port, thread_port, task_port, */ { - register ipc_pset_t dest_pset; + ipc_pset_t dest_pset; dest_pset = dest_port->ip_pset; if (dest_pset == IPS_NULL) @@ -490,7 +485,7 @@ exception_raise(dest_port, thread_port, task_port, * Release the receiver's reference for his object. */ { - register ipc_object_t object = receiver->ith_object; + ipc_object_t object = receiver->ith_object; io_lock(object); io_release(object); @@ -498,7 +493,7 @@ exception_raise(dest_port, thread_port, task_port, } { - register struct mach_exception *exc = + struct mach_exception *exc = (struct mach_exception *) &kmsg->ikm_header; ipc_space_t space = receiver->task->itk_space; @@ -609,30 +604,18 @@ exception_raise(dest_port, thread_port, task_port, ip_unlock(reply_port); { - register ipc_entry_t table; - register ipc_entry_t entry; - register mach_port_index_t index; - - /* optimized ipc_entry_get */ - - table = space->is_table; - index = table->ie_next; + kern_return_t kr; + ipc_entry_t entry; - if (index == 0) + kr = ipc_entry_get (space, &exc->Head.msgh_remote_port, &entry); + if (kr) goto abort_copyout; - - entry = &table[index]; - table->ie_next = entry->ie_next; - entry->ie_request = 0; - { - register mach_port_gen_t gen; + mach_port_gen_t gen; assert((entry->ie_bits &~ IE_BITS_GEN_MASK) == 0); gen = entry->ie_bits + IE_BITS_GEN_ONE; - exc->Head.msgh_remote_port = MACH_PORT_MAKE(index, gen); - /* optimized ipc_right_copyout */ entry->ie_bits = gen | (MACH_PORT_TYPE_SEND_ONCE | 1); @@ -710,7 +693,7 @@ exception_raise(dest_port, thread_port, task_port, #endif slow_exception_raise: { - register struct mach_exception *exc = + struct mach_exception *exc = (struct mach_exception *) &kmsg->ikm_header; ipc_kmsg_t reply_kmsg; mach_port_seqno_t reply_seqno; @@ -772,6 +755,12 @@ exception_raise(dest_port, thread_port, task_port, } } +/* Macro used by MIG to cleanly check the type. */ +#define BAD_TYPECHECK(type, check) unlikely (({\ + union { mach_msg_type_t t; unsigned32_t w; } _t, _c;\ + _t.t = *(type); _c.t = *(check);_t.w != _c.w; })) + +/* Type descriptor for the return code. */ mach_msg_type_t exc_RetCode_proto = { /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32, /* msgt_size = */ 32, @@ -794,10 +783,9 @@ mach_msg_type_t exc_RetCode_proto = { */ kern_return_t -exception_parse_reply(kmsg) - ipc_kmsg_t kmsg; +exception_parse_reply(ipc_kmsg_t kmsg) { - register mig_reply_header_t *msg = + mig_reply_header_t *msg = (mig_reply_header_t *) &kmsg->ikm_header; kern_return_t kr; @@ -805,7 +793,7 @@ exception_parse_reply(kmsg) MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0)) || (msg->Head.msgh_size != sizeof *msg) || (msg->Head.msgh_id != MACH_EXCEPTION_REPLY_ID) || - (* (int *) &msg->RetCodeType != * (int *) &exc_RetCode_proto)) { + (BAD_TYPECHECK(&msg->RetCodeType, &exc_RetCode_proto))) { /* * Bozo user sent us a misformatted reply. */ @@ -839,7 +827,7 @@ exception_parse_reply(kmsg) */ void -exception_raise_continue() +exception_raise_continue(void) { ipc_thread_t self = current_thread(); ipc_port_t reply_port = self->ith_port; @@ -871,10 +859,10 @@ exception_raise_continue() */ void -exception_raise_continue_slow(mr, kmsg, seqno) - mach_msg_return_t mr; - ipc_kmsg_t kmsg; - mach_port_seqno_t seqno; +exception_raise_continue_slow( + mach_msg_return_t mr, + ipc_kmsg_t kmsg, + mach_port_seqno_t seqno) { ipc_thread_t self = current_thread(); ipc_port_t reply_port = self->ith_port; @@ -954,9 +942,9 @@ exception_raise_continue_slow(mr, kmsg, seqno) */ void -exception_raise_continue_fast(reply_port, kmsg) - ipc_port_t reply_port; - ipc_kmsg_t kmsg; +exception_raise_continue_fast( + ipc_port_t reply_port, + ipc_kmsg_t kmsg) { ipc_thread_t self = current_thread(); kern_return_t kr; diff --git a/kern/exception.h b/kern/exception.h new file mode 100644 index 00000000..55902dd1 --- /dev/null +++ b/kern/exception.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013 Free Software Foundation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _KERN_EXCEPTION_H_ +#define _KERN_EXCEPTION_H_ + +#include <ipc/ipc_types.h> +#include <ipc/ipc_kmsg.h> + +extern void +exception( + integer_t _exception, + integer_t code, + integer_t subcode) __attribute__ ((noreturn)); + +extern void +exception_try_task( + integer_t _exception, + integer_t code, + integer_t subcode) __attribute__ ((noreturn)); + +extern void +exception_no_server(void) __attribute__ ((noreturn)); + +extern void +exception_raise( + ipc_port_t dest_port, + ipc_port_t thread_port, + ipc_port_t task_port, + integer_t _exception, + integer_t code, + integer_t subcode) __attribute__ ((noreturn)); + +extern kern_return_t +exception_parse_reply(ipc_kmsg_t kmsg); + +extern void +exception_raise_continue(void) __attribute__ ((noreturn)); + +extern void +exception_raise_continue_slow( + mach_msg_return_t mr, + ipc_kmsg_t kmsg, + mach_port_seqno_t seqno) __attribute__ ((noreturn)); + +extern void +exception_raise_continue_fast( + ipc_port_t reply_port, + ipc_kmsg_t kmsg) __attribute__ ((noreturn)); + +#endif /* _KERN_EXCEPTION_H_ */ diff --git a/kern/host.c b/kern/host.c index 57a40b43..2855cd2d 100644 --- a/kern/host.c +++ b/kern/host.c @@ -47,12 +47,12 @@ host_data_t realhost; kern_return_t host_processors( - host_t host, + const host_t host, processor_array_t *processor_list, natural_t *countp) { - register int i; - register processor_t *tp; + int i; + processor_t *tp; vm_offset_t addr; unsigned int count; @@ -95,12 +95,12 @@ kern_return_t host_processors( } kern_return_t host_info( - host_t host, + const host_t host, int flavor, host_info_t info, natural_t *count) { - register integer_t i, *slot_ptr; + integer_t i, *slot_ptr; if (host == HOST_NULL) return KERN_INVALID_ARGUMENT; @@ -109,7 +109,7 @@ kern_return_t host_info( case HOST_BASIC_INFO: { - register host_basic_info_t basic_info; + host_basic_info_t basic_info; /* * Basic information about this host. @@ -152,7 +152,7 @@ kern_return_t host_info( case HOST_SCHED_INFO: { - register host_sched_info_t sched_info; + host_sched_info_t sched_info; extern int min_quantum; /* minimum quantum, in microseconds */ @@ -174,7 +174,7 @@ kern_return_t host_info( case HOST_LOAD_INFO: { - register host_load_info_t load_info; + host_load_info_t load_info; extern long avenrun[3], mach_factor[3]; if (*count < HOST_LOAD_INFO_COUNT) @@ -204,7 +204,7 @@ kern_return_t host_info( */ kern_return_t host_kernel_version( - host_t host, + const host_t host, kernel_version_t out_version) { extern char version[]; @@ -225,7 +225,7 @@ kern_return_t host_kernel_version( #if MACH_HOST kern_return_t host_processor_sets( - host_t host, + const host_t host, processor_set_name_array_t *pset_list, natural_t *count) { @@ -302,7 +302,7 @@ host_processor_sets( return KERN_RESOURCE_SHORTAGE; } - memcpy((char *) newaddr, (char *) addr, size_needed); + memcpy((void *) newaddr, (void *) addr, size_needed); kfree(addr, size); psets = (processor_set_t *) newaddr; } @@ -324,7 +324,7 @@ host_processor_sets( */ kern_return_t host_processor_sets( - host_t host, + const host_t host, processor_set_name_array_t *pset_list, natural_t *count) { @@ -362,7 +362,7 @@ host_processor_sets( */ kern_return_t host_processor_set_priv( - host_t host, + const host_t host, processor_set_t pset_name, processor_set_t *pset) { diff --git a/kern/ipc_host.c b/kern/ipc_host.c index cd1c11ab..a02eb6f6 100644 --- a/kern/ipc_host.c +++ b/kern/ipc_host.c @@ -205,7 +205,7 @@ ipc_pset_terminate( */ kern_return_t processor_set_default( - host_t host, + const host_t host, processor_set_t *pset) { if (host == HOST_NULL) diff --git a/kern/ipc_kobject.c b/kern/ipc_kobject.c index 37d4eb99..709ec9ec 100644 --- a/kern/ipc_kobject.c +++ b/kern/ipc_kobject.c @@ -49,8 +49,21 @@ #include <vm/memory_object_proxy.h> #include <device/ds_routines.h> +#include <kern/mach.server.h> +#include <ipc/mach_port.server.h> +#include <kern/mach_host.server.h> +#include <device/device.server.h> +#include <device/device_pager.server.h> +#include <kern/mach4.server.h> +#include <kern/gnumach.server.h> + +#if MACH_DEBUG +#include <kern/mach_debug.server.h> +#endif + #if MACH_MACHINE_ROUTINES #include <machine/machine_routines.h> +#include MACHINE_SERVER_HEADER #endif @@ -146,21 +159,6 @@ ipc_kobject_server(request) * to perform the kernel function */ { - extern mig_routine_t mach_server_routine(), - mach_port_server_routine(), - mach_host_server_routine(), - device_server_routine(), - device_pager_server_routine(), - mach4_server_routine(), - gnumach_server_routine(); -#if MACH_DEBUG - extern mig_routine_t mach_debug_server_routine(); -#endif - -#if MACH_MACHINE_ROUTINES - extern mig_routine_t MACHINE_SERVER_ROUTINE(); -#endif - check_simple_locks(); if ((routine = mach_server_routine(&request->ikm_header)) != 0 || (routine = mach_port_server_routine(&request->ikm_header)) != 0 @@ -246,7 +244,7 @@ ipc_kobject_server(request) } else { /* * The message contents of the request are intact. - * Destroy everthing except the reply port right, + * Destroy everything except the reply port right, * which is needed in the reply message. */ diff --git a/kern/ipc_kobject.h b/kern/ipc_kobject.h index cb795741..606a66a9 100644 --- a/kern/ipc_kobject.h +++ b/kern/ipc_kobject.h @@ -36,13 +36,12 @@ * Declarations for letting a port represent a kernel object. */ -#include <ipc/ipc_kmsg.h> -#include <ipc/ipc_types.h> - #ifndef _KERN_IPC_KOBJECT_H_ #define _KERN_IPC_KOBJECT_H_ #include <mach/machine/vm_types.h> +#include <ipc/ipc_types.h> +#include <ipc/ipc_kmsg.h> typedef vm_offset_t ipc_kobject_t; diff --git a/kern/ipc_mig.c b/kern/ipc_mig.c index 3f55da7c..22dac420 100644 --- a/kern/ipc_mig.c +++ b/kern/ipc_mig.c @@ -37,6 +37,7 @@ #include <kern/task.h> #include <kern/ipc_kobject.h> #include <kern/ipc_tt.h> +#include <kern/ipc_mig.h> #include <vm/vm_map.h> #include <vm/vm_user.h> #include <ipc/port.h> @@ -91,7 +92,7 @@ mach_msg_send_from_kernel( mach_msg_return_t mach_msg_rpc_from_kernel(msg, send_size, reply_size) - mach_msg_header_t *msg; + const mach_msg_header_t *msg; mach_msg_size_t send_size; mach_msg_size_t reply_size; { @@ -109,8 +110,7 @@ mach_msg_rpc_from_kernel(msg, send_size, reply_size) */ void -mach_msg_abort_rpc(thread) - ipc_thread_t thread; +mach_msg_abort_rpc(ipc_thread_t thread) { ipc_port_t reply = IP_NULL; @@ -140,14 +140,14 @@ mach_msg_abort_rpc(thread) */ mach_msg_return_t -mach_msg(msg, option, send_size, rcv_size, rcv_name, time_out, notify) - mach_msg_header_t *msg; - mach_msg_option_t option; - mach_msg_size_t send_size; - mach_msg_size_t rcv_size; - mach_port_t rcv_name; - mach_msg_timeout_t time_out; - mach_port_t notify; +mach_msg( + mach_msg_header_t *msg, + mach_msg_option_t option, + mach_msg_size_t send_size, + mach_msg_size_t rcv_size, + mach_port_t rcv_name, + mach_msg_timeout_t time_out, + mach_port_t notify) { ipc_space_t space = current_space(); vm_map_t map = current_map(); @@ -271,10 +271,10 @@ mig_put_reply_port( /* * mig_strncpy.c - by Joshua Block * - * mig_strncp -- Bounded string copy. Does what the library routine strncpy - * OUGHT to do: Copies the (null terminated) string in src into dest, a - * buffer of length len. Assures that the copy is still null terminated - * and doesn't overflow the buffer, truncating the copy if necessary. + * mig_strncpy -- Bounded string copy. Does what the library routine + * strncpy does: Copies the (null terminated) string in src into dest, + * a buffer of length len. Returns the length of the destination + * string excluding the terminating null. * * Parameters: * @@ -284,37 +284,44 @@ mig_put_reply_port( * * len - Length of destination buffer. */ -void mig_strncpy(dest, src, len) -char *dest, *src; -int len; +vm_size_t +mig_strncpy(dest, src, len) + char *dest; + const char *src; + int len; { - int i; + char *dest_ = dest; + int i; - if (len <= 0) - return; + if (len <= 0) + return 0; - for (i=1; i<len; i++) - if (! (*dest++ = *src++)) - return; + for (i = 0; i < len; i++) { + if (! (*dest = *src)) + break; + dest++; + src++; + } - *dest = '\0'; - return; + return dest - dest_; } #define fast_send_right_lookup(name, port, abort) \ MACRO_BEGIN \ - register ipc_space_t space = current_space(); \ - register ipc_entry_t entry; \ - register mach_port_index_t index = MACH_PORT_INDEX(name); \ + ipc_space_t space = current_space(); \ + ipc_entry_t entry; \ \ is_read_lock(space); \ assert(space->is_active); \ \ - if ((index >= space->is_table_size) || \ - (((entry = &space->is_table[index])->ie_bits & \ - (IE_BITS_GEN_MASK|MACH_PORT_TYPE_SEND)) != \ - (MACH_PORT_GEN(name) | MACH_PORT_TYPE_SEND))) { \ - is_read_unlock(space); \ + entry = ipc_entry_lookup (space, name); \ + if (entry == IE_NULL) { \ + is_read_unlock (space); \ + abort; \ + } \ + \ + if (IE_BITS_TYPE (entry->ie_bits) != MACH_PORT_TYPE_SEND) { \ + is_read_unlock (space); \ abort; \ } \ \ @@ -327,11 +334,10 @@ MACRO_BEGIN \ MACRO_END device_t -port_name_to_device(name) - mach_port_t name; +port_name_to_device(mach_port_t name) { - register ipc_port_t port; - register device_t device; + ipc_port_t port; + device_t device; fast_send_right_lookup(name, port, goto abort); /* port is locked */ @@ -371,17 +377,16 @@ port_name_to_device(name) } thread_t -port_name_to_thread(name) - mach_port_t name; +port_name_to_thread(mach_port_t name) { - register ipc_port_t port; + ipc_port_t port; fast_send_right_lookup(name, port, goto abort); /* port is locked */ if (ip_active(port) && (ip_kotype(port) == IKOT_THREAD)) { - register thread_t thread; + thread_t thread; thread = (thread_t) port->ip_kobject; assert(thread != THREAD_NULL); @@ -417,17 +422,16 @@ port_name_to_thread(name) } task_t -port_name_to_task(name) - mach_port_t name; +port_name_to_task(mach_port_t name) { - register ipc_port_t port; + ipc_port_t port; fast_send_right_lookup(name, port, goto abort); /* port is locked */ if (ip_active(port) && (ip_kotype(port) == IKOT_TASK)) { - register task_t task; + task_t task; task = (task_t) port->ip_kobject; assert(task != TASK_NULL); @@ -468,14 +472,14 @@ vm_map_t port_name_to_map( mach_port_t name) { - register ipc_port_t port; + ipc_port_t port; fast_send_right_lookup(name, port, goto abort); /* port is locked */ if (ip_active(port) && (ip_kotype(port) == IKOT_TASK)) { - register vm_map_t map; + vm_map_t map; map = ((task_t) port->ip_kobject)->map; assert(map != VM_MAP_NULL); @@ -513,17 +517,16 @@ port_name_to_map( } ipc_space_t -port_name_to_space(name) - mach_port_t name; +port_name_to_space(mach_port_t name) { - register ipc_port_t port; + ipc_port_t port; fast_send_right_lookup(name, port, goto abort); /* port is locked */ if (ip_active(port) && (ip_kotype(port) == IKOT_TASK)) { - register ipc_space_t space; + ipc_space_t space; space = ((task_t) port->ip_kobject)->itk_space; assert(space != IS_NULL); @@ -569,12 +572,11 @@ port_name_to_space(name) * AARGH! */ -kern_return_t thread_get_state_KERNEL(thread_port, flavor, - old_state, old_state_count) - mach_port_t thread_port; /* port right for thread */ - int flavor; - thread_state_t old_state; /* pointer to OUT array */ - natural_t *old_state_count; /* IN/OUT */ +kern_return_t thread_get_state_KERNEL( + mach_port_t thread_port, /* port right for thread */ + int flavor, + thread_state_t old_state, /* pointer to OUT array */ + natural_t *old_state_count) /* IN/OUT */ { thread_t thread; kern_return_t result; @@ -586,12 +588,11 @@ kern_return_t thread_get_state_KERNEL(thread_port, flavor, return result; } -kern_return_t thread_set_state_KERNEL(thread_port, flavor, - new_state, new_state_count) - mach_port_t thread_port; /* port right for thread */ - int flavor; - thread_state_t new_state; - natural_t new_state_count; +kern_return_t thread_set_state_KERNEL( + mach_port_t thread_port, /* port right for thread */ + int flavor, + thread_state_t new_state, + natural_t new_state_count) { thread_t thread; kern_return_t result; @@ -613,7 +614,7 @@ kern_return_t thread_set_state_KERNEL(thread_port, flavor, * knows to fall back on an RPC. For other return values, it won't * retry with an RPC. The retry might get a different (incorrect) rc. * Return values are only set (and should only be set, with copyout) - * on successfull calls. + * on successful calls. */ kern_return_t @@ -650,12 +651,12 @@ syscall_vm_map( } else port = (ipc_port_t) memory_object; - copyin((char *)address, (char *)&addr, sizeof(vm_offset_t)); + copyin(address, &addr, sizeof(vm_offset_t)); result = vm_map(map, &addr, size, mask, anywhere, port, offset, copy, cur_protection, max_protection, inheritance); if (result == KERN_SUCCESS) - copyout((char *)&addr, (char *)address, sizeof(vm_offset_t)); + copyout(&addr, address, sizeof(vm_offset_t)); if (IP_VALID(port)) ipc_port_release_send(port); vm_map_deallocate(map); @@ -663,11 +664,11 @@ syscall_vm_map( return result; } -kern_return_t syscall_vm_allocate(target_map, address, size, anywhere) - mach_port_t target_map; - vm_offset_t *address; - vm_size_t size; - boolean_t anywhere; +kern_return_t syscall_vm_allocate( + mach_port_t target_map, + vm_offset_t *address, + vm_size_t size, + boolean_t anywhere) { vm_map_t map; vm_offset_t addr; @@ -677,19 +678,19 @@ kern_return_t syscall_vm_allocate(target_map, address, size, anywhere) if (map == VM_MAP_NULL) return MACH_SEND_INTERRUPTED; - copyin((char *)address, (char *)&addr, sizeof(vm_offset_t)); + copyin(address, &addr, sizeof(vm_offset_t)); result = vm_allocate(map, &addr, size, anywhere); if (result == KERN_SUCCESS) - copyout((char *)&addr, (char *)address, sizeof(vm_offset_t)); + copyout(&addr, address, sizeof(vm_offset_t)); vm_map_deallocate(map); return result; } -kern_return_t syscall_vm_deallocate(target_map, start, size) - mach_port_t target_map; - vm_offset_t start; - vm_size_t size; +kern_return_t syscall_vm_deallocate( + mach_port_t target_map, + vm_offset_t start, + vm_size_t size) { vm_map_t map; kern_return_t result; @@ -704,10 +705,10 @@ kern_return_t syscall_vm_deallocate(target_map, start, size) return result; } -kern_return_t syscall_task_create(parent_task, inherit_memory, child_task) - mach_port_t parent_task; - boolean_t inherit_memory; - mach_port_t *child_task; /* OUT */ +kern_return_t syscall_task_create( + mach_port_t parent_task, + boolean_t inherit_memory, + mach_port_t *child_task) /* OUT */ { task_t t, c; ipc_port_t port; @@ -725,7 +726,7 @@ kern_return_t syscall_task_create(parent_task, inherit_memory, child_task) (void) ipc_kmsg_copyout_object(current_space(), (ipc_object_t) port, MACH_MSG_TYPE_PORT_SEND, &name); - copyout((char *)&name, (char *)child_task, + copyout(&name, child_task, sizeof(mach_port_t)); } task_deallocate(t); @@ -733,8 +734,7 @@ kern_return_t syscall_task_create(parent_task, inherit_memory, child_task) return result; } -kern_return_t syscall_task_terminate(task) - mach_port_t task; +kern_return_t syscall_task_terminate(mach_port_t task) { task_t t; kern_return_t result; @@ -749,8 +749,7 @@ kern_return_t syscall_task_terminate(task) return result; } -kern_return_t syscall_task_suspend(task) - mach_port_t task; +kern_return_t syscall_task_suspend(mach_port_t task) { task_t t; kern_return_t result; @@ -765,10 +764,10 @@ kern_return_t syscall_task_suspend(task) return result; } -kern_return_t syscall_task_set_special_port(task, which_port, port_name) - mach_port_t task; - int which_port; - mach_port_t port_name; +kern_return_t syscall_task_set_special_port( + mach_port_t task, + int which_port, + mach_port_t port_name) { task_t t; ipc_port_t port; @@ -798,10 +797,10 @@ kern_return_t syscall_task_set_special_port(task, which_port, port_name) } kern_return_t -syscall_mach_port_allocate(task, right, namep) - mach_port_t task; - mach_port_right_t right; - mach_port_t *namep; +syscall_mach_port_allocate( + mach_port_t task, + mach_port_right_t right, + mach_port_t *namep) { ipc_space_t space; mach_port_t name; @@ -813,17 +812,17 @@ syscall_mach_port_allocate(task, right, namep) kr = mach_port_allocate(space, right, &name); if (kr == KERN_SUCCESS) - copyout((char *)&name, (char *)namep, sizeof(mach_port_t)); + copyout(&name, namep, sizeof(mach_port_t)); is_release(space); return kr; } kern_return_t -syscall_mach_port_allocate_name(task, right, name) - mach_port_t task; - mach_port_right_t right; - mach_port_t name; +syscall_mach_port_allocate_name( + mach_port_t task, + mach_port_right_t right, + mach_port_t name) { ipc_space_t space; kern_return_t kr; @@ -839,9 +838,9 @@ syscall_mach_port_allocate_name(task, right, name) } kern_return_t -syscall_mach_port_deallocate(task, name) - mach_port_t task; - mach_port_t name; +syscall_mach_port_deallocate( + mach_port_t task, + mach_port_t name) { ipc_space_t space; kern_return_t kr; @@ -857,11 +856,11 @@ syscall_mach_port_deallocate(task, name) } kern_return_t -syscall_mach_port_insert_right(task, name, right, rightType) - mach_port_t task; - mach_port_t name; - mach_port_t right; - mach_msg_type_name_t rightType; +syscall_mach_port_insert_right( + mach_port_t task, + mach_port_t name, + mach_port_t right, + mach_msg_type_name_t rightType) { ipc_space_t space; ipc_object_t object; @@ -896,8 +895,7 @@ syscall_mach_port_insert_right(task, name, right, rightType) return kr; } -kern_return_t syscall_thread_depress_abort(thread) - mach_port_t thread; +kern_return_t syscall_thread_depress_abort(mach_port_t thread) { thread_t t; kern_return_t result; @@ -915,10 +913,6 @@ kern_return_t syscall_thread_depress_abort(thread) /* * Device traps -- these are way experimental. */ - -extern io_return_t ds_device_write_trap(); -extern io_return_t ds_device_writev_trap(); - io_return_t syscall_device_write_request(mach_port_t device_name, mach_port_t reply_name, @@ -928,7 +922,7 @@ syscall_device_write_request(mach_port_t device_name, vm_size_t data_count) { device_t dev; - ipc_port_t reply_port; + /*ipc_port_t reply_port;*/ io_return_t res; /* @@ -949,9 +943,10 @@ syscall_device_write_request(mach_port_t device_name, /* * Translate reply port. */ - if (reply_name == MACH_PORT_NULL) + /*if (reply_name == MACH_PORT_NULL) reply_port = IP_NULL; - else { + */ + if (reply_name != MACH_PORT_NULL) { /* Homey don't play that. */ device_deallocate(dev); return KERN_INVALID_RIGHT; @@ -978,7 +973,7 @@ syscall_device_writev_request(mach_port_t device_name, vm_size_t iocount) { device_t dev; - ipc_port_t reply_port; + /*ipc_port_t reply_port;*/ io_return_t res; /* @@ -999,9 +994,10 @@ syscall_device_writev_request(mach_port_t device_name, /* * Translate reply port. */ - if (reply_name == MACH_PORT_NULL) + /*if (reply_name == MACH_PORT_NULL) reply_port = IP_NULL; - else { + */ + if (reply_name != MACH_PORT_NULL) { /* Homey don't play that. */ device_deallocate(dev); return KERN_INVALID_RIGHT; diff --git a/kern/ipc_mig.h b/kern/ipc_mig.h index f352bdc6..6f063eca 100644 --- a/kern/ipc_mig.h +++ b/kern/ipc_mig.h @@ -27,6 +27,7 @@ #define _IPC_MIG_H_ #include <mach/std_types.h> +#include <device/device_types.h> /* * Routine: mach_msg_send_from_kernel @@ -58,8 +59,84 @@ extern mach_msg_return_t mach_msg_send_from_kernel( extern void mach_msg_abort_rpc (ipc_thread_t); extern mach_msg_return_t mach_msg_rpc_from_kernel( - mach_msg_header_t *msg, + const mach_msg_header_t *msg, mach_msg_size_t send_size, mach_msg_size_t reply_size); +extern kern_return_t syscall_vm_map( + mach_port_t target_map, + vm_offset_t *address, + vm_size_t size, + vm_offset_t mask, + boolean_t anywhere, + mach_port_t memory_object, + vm_offset_t offset, + boolean_t copy, + vm_prot_t cur_protection, + vm_prot_t max_protection, + vm_inherit_t inheritance); + +extern kern_return_t syscall_vm_allocate( + mach_port_t target_map, + vm_offset_t *address, + vm_size_t size, + boolean_t anywhere); + +extern kern_return_t syscall_vm_deallocate( + mach_port_t target_map, + vm_offset_t start, + vm_size_t size); + +extern kern_return_t syscall_task_create( + mach_port_t parent_task, + boolean_t inherit_memory, + mach_port_t *child_task); + +extern kern_return_t syscall_task_terminate(mach_port_t task); + +extern kern_return_t syscall_task_suspend(mach_port_t task); + +extern kern_return_t syscall_task_set_special_port( + mach_port_t task, + int which_port, + mach_port_t port_name); + +extern kern_return_t syscall_mach_port_allocate( + mach_port_t task, + mach_port_right_t right, + mach_port_t *namep); + +extern kern_return_t syscall_mach_port_deallocate( + mach_port_t task, + mach_port_t name); + +extern kern_return_t syscall_mach_port_insert_right( + mach_port_t task, + mach_port_t name, + mach_port_t right, + mach_msg_type_name_t rightType); + +extern kern_return_t syscall_mach_port_allocate_name( + mach_port_t task, + mach_port_right_t right, + mach_port_t name); + +extern kern_return_t syscall_thread_depress_abort(mach_port_t thread); + +extern io_return_t syscall_device_write_request( + mach_port_t device_name, + mach_port_t reply_name, + dev_mode_t mode, + recnum_t recnum, + vm_offset_t data, + vm_size_t data_count); + +io_return_t syscall_device_writev_request( + mach_port_t device_name, + mach_port_t reply_name, + dev_mode_t mode, + recnum_t recnum, + io_buf_vec_t *iovec, + vm_size_t iocount); + #endif /* _IPC_MIG_H_ */ diff --git a/kern/ipc_sched.c b/kern/ipc_sched.c index 615ad608..be82971b 100644 --- a/kern/ipc_sched.c +++ b/kern/ipc_sched.c @@ -182,9 +182,9 @@ thread_will_wait_with_timeout( boolean_t thread_handoff( - register thread_t old, - register continuation_t continuation, - register thread_t new) + thread_t old, + continuation_t continuation, + thread_t new) { spl_t s; @@ -214,7 +214,7 @@ thread_handoff( thread_unlock(new); (void) splx(s); - counter_always(c_thread_handoff_misses++); + counter(c_thread_handoff_misses++); return FALSE; } @@ -268,7 +268,7 @@ thread_handoff( */ old->wake_active = FALSE; thread_unlock(old); - thread_wakeup((event_t)&old->wake_active); + thread_wakeup(TH_EV_WAKE_ACTIVE(old)); goto after_old_thread; } } else @@ -278,6 +278,6 @@ thread_handoff( after_old_thread: (void) splx(s); - counter_always(c_thread_handoff_hits++); + counter(c_thread_handoff_hits++); return TRUE; } diff --git a/kern/ipc_tt.c b/kern/ipc_tt.c index 6d32e5b0..e4d657b7 100644 --- a/kern/ipc_tt.c +++ b/kern/ipc_tt.c @@ -72,7 +72,7 @@ ipc_task_init( int i; - kr = ipc_space_create(&ipc_table_entries[0], &space); + kr = ipc_space_create(&space); if (kr != KERN_SUCCESS) panic("ipc_task_init"); @@ -213,8 +213,7 @@ ipc_task_terminate( */ void -ipc_thread_init(thread) - thread_t thread; +ipc_thread_init(thread_t thread) { ipc_port_t kport; @@ -243,8 +242,7 @@ ipc_thread_init(thread) */ void -ipc_thread_enable(thread) - thread_t thread; +ipc_thread_enable(thread_t thread) { ipc_port_t kport; @@ -264,8 +262,7 @@ ipc_thread_enable(thread) */ void -ipc_thread_disable(thread) - thread_t thread; +ipc_thread_disable(thread_t thread) { ipc_port_t kport; @@ -286,8 +283,7 @@ ipc_thread_disable(thread) */ void -ipc_thread_terminate(thread) - thread_t thread; +ipc_thread_terminate(thread_t thread) { ipc_port_t kport; @@ -387,9 +383,9 @@ retrieve_thread_self(thread) ipc_port_t retrieve_task_self_fast( - register task_t task) + task_t task) { - register ipc_port_t port; + ipc_port_t port; assert(task == current_task()); @@ -424,10 +420,9 @@ retrieve_task_self_fast( */ ipc_port_t -retrieve_thread_self_fast(thread) - register thread_t thread; +retrieve_thread_self_fast(thread_t thread) { - register ipc_port_t port; + ipc_port_t port; assert(thread == current_thread()); @@ -648,9 +643,9 @@ task_get_special_port( kern_return_t task_set_special_port( - task_t task, - int which, - ipc_port_t port) + task_t task, + int which, + const ipc_port_t port) { ipc_port_t *whichp; ipc_port_t old; @@ -705,10 +700,10 @@ task_set_special_port( */ kern_return_t -thread_get_special_port(thread, which, portp) - thread_t thread; - int which; - ipc_port_t *portp; +thread_get_special_port( + thread_t thread, + int which, + ipc_port_t *portp) { ipc_port_t *whichp; ipc_port_t port; @@ -758,10 +753,10 @@ thread_get_special_port(thread, which, portp) */ kern_return_t -thread_set_special_port(thread, which, port) - thread_t thread; - int which; - ipc_port_t port; +thread_set_special_port( + thread_t thread, + int which, + ipc_port_t port) { ipc_port_t *whichp; ipc_port_t old; @@ -890,10 +885,10 @@ mach_ports_register( */ kern_return_t -mach_ports_lookup(task, portsp, portsCnt) - task_t task; - ipc_port_t **portsp; - mach_msg_type_number_t *portsCnt; +mach_ports_lookup( + task_t task, + ipc_port_t **portsp, + mach_msg_type_number_t *portsCnt) { vm_offset_t memory; vm_size_t size; @@ -1003,8 +998,7 @@ convert_port_to_space( */ vm_map_t -convert_port_to_map(port) - ipc_port_t port; +convert_port_to_map(ipc_port_t port) { vm_map_t map = VM_MAP_NULL; @@ -1032,8 +1026,7 @@ convert_port_to_map(port) */ thread_t -convert_port_to_thread(port) - ipc_port_t port; +convert_port_to_thread(ipc_port_t port) { thread_t thread = THREAD_NULL; @@ -1061,8 +1054,7 @@ convert_port_to_thread(port) */ ipc_port_t -convert_task_to_port(task) - task_t task; +convert_task_to_port(task_t task) { ipc_port_t port; @@ -1088,8 +1080,7 @@ convert_task_to_port(task) */ ipc_port_t -convert_thread_to_port(thread) - thread_t thread; +convert_thread_to_port(thread_t thread) { ipc_port_t port; @@ -1113,8 +1104,7 @@ convert_thread_to_port(thread) */ void -space_deallocate(space) - ipc_space_t space; +space_deallocate(ipc_space_t space) { if (space != IS_NULL) is_release(space); diff --git a/kern/list.h b/kern/list.h index 03414718..be927625 100644 --- a/kern/list.h +++ b/kern/list.h @@ -31,9 +31,7 @@ #include <stddef.h> #include <sys/types.h> - -#define structof(ptr, type, member) \ - ((type *)((char *)ptr - offsetof(type, member))) +#include <kern/macros.h> /* * Structure used as both head and node. @@ -240,7 +238,7 @@ static inline void list_add(struct list *prev, struct list *next, /* * Insert a node at the head of a list. */ -static inline void list_insert(struct list *list, struct list *node) +static inline void list_insert_head(struct list *list, struct list *node) { list_add(list, list->next, node); } diff --git a/kern/lock.c b/kern/lock.c index 44d4448e..3c74fec8 100644 --- a/kern/lock.c +++ b/kern/lock.c @@ -133,7 +133,7 @@ unsigned int simple_locks_taken = 0; struct simple_locks_info { simple_lock_t l; - unsigned int ra; + void *ra; } simple_locks_info[NSLINFO]; void check_simple_locks(void) @@ -161,10 +161,8 @@ void simple_lock( info = &simple_locks_info[simple_locks_taken++]; info->l = l; - /* XXX we want our return address, if possible */ -#if defined(__i386__) - info->ra = *((unsigned long *)&l - 1); -#endif /* i386 */ + info->ra = + __builtin_extract_return_addr (__builtin_return_address (0)); } boolean_t simple_lock_try( @@ -179,10 +177,8 @@ boolean_t simple_lock_try( info = &simple_locks_info[simple_locks_taken++]; info->l = l; - /* XXX we want our return address, if possible */ -#if defined(__i386__) - info->ra = *((unsigned long *)&l - 1); -#endif /* i386 */ + info->ra = + __builtin_extract_return_addr (__builtin_return_address (0)); return TRUE; } @@ -250,9 +246,9 @@ void lock_sleepable( */ void lock_write( - register lock_t l) + lock_t l) { - register int i; + int i; check_simple_locks(); simple_lock(&l->interlock); @@ -308,7 +304,7 @@ void lock_write( } void lock_done( - register lock_t l) + lock_t l) { simple_lock(&l->interlock); @@ -340,9 +336,9 @@ void lock_done( } void lock_read( - register lock_t l) + lock_t l) { - register int i; + int i; check_simple_locks(); simple_lock(&l->interlock); @@ -387,9 +383,9 @@ void lock_read( * Returns TRUE if the upgrade *failed*. */ boolean_t lock_read_to_write( - register lock_t l) + lock_t l) { - register int i; + int i; check_simple_locks(); simple_lock(&l->interlock); @@ -443,7 +439,7 @@ boolean_t lock_read_to_write( } void lock_write_to_read( - register lock_t l) + lock_t l) { simple_lock(&l->interlock); @@ -474,7 +470,7 @@ void lock_write_to_read( */ boolean_t lock_try_write( - register lock_t l) + lock_t l) { simple_lock(&l->interlock); @@ -513,7 +509,7 @@ boolean_t lock_try_write( */ boolean_t lock_try_read( - register lock_t l) + lock_t l) { simple_lock(&l->interlock); @@ -547,7 +543,7 @@ boolean_t lock_try_read( * Returns FALSE if the upgrade *failed*. */ boolean_t lock_try_read_to_write( - register lock_t l) + lock_t l) { check_simple_locks(); simple_lock(&l->interlock); diff --git a/kern/lock.h b/kern/lock.h index a8f2fd1c..a6d286a1 100644 --- a/kern/lock.h +++ b/kern/lock.h @@ -94,7 +94,9 @@ extern void check_simple_locks(void); /* * Do not allocate storage for locks if not needed. */ -#define decl_simple_lock_data(class,name) +struct simple_lock_data_empty {}; +#define decl_simple_lock_data(class,name) \ +class struct simple_lock_data_empty name; #define simple_lock_addr(lock) ((simple_lock_t)0) /* @@ -102,7 +104,7 @@ extern void check_simple_locks(void); */ #define simple_lock_init(l) #define simple_lock(l) -#define simple_unlock(l) +#define simple_unlock(l) ((void)(l)) #define simple_lock_try(l) (TRUE) /* always succeeds */ #define simple_lock_taken(l) (1) /* always succeeds */ #define check_simple_locks() @@ -171,4 +173,6 @@ extern boolean_t lock_try_read_to_write(lock_t); extern void lock_set_recursive(lock_t); extern void lock_clear_recursive(lock_t); +void db_show_all_slocks(void); + #endif /* _KERN_LOCK_H_ */ diff --git a/kern/lock_mon.c b/kern/lock_mon.c index 14504281..f6bbd5dd 100644 --- a/kern/lock_mon.c +++ b/kern/lock_mon.c @@ -64,7 +64,6 @@ typedef unsigned int time_stamp_t; #define LOCK_INFO_HASH_COUNT 1024 #define LOCK_INFO_PER_BUCKET (LOCK_INFO_MAX/LOCK_INFO_HASH_COUNT) - #define HASH_LOCK(lock) ((long)lock>>5 & (LOCK_INFO_HASH_COUNT-1)) struct lock_info { @@ -85,7 +84,7 @@ struct lock_info_bucket lock_info[LOCK_INFO_HASH_COUNT]; struct lock_info default_lock_info; unsigned default_lock_stack = 0; -extern int curr_ipl[]; +extern spl_t curr_ipl[]; @@ -94,8 +93,8 @@ locate_lock_info(lock) decl_simple_lock_data(, **lock) { struct lock_info *li = &(lock_info[HASH_LOCK(*lock)].info[0]); - register i; - register my_cpu = cpu_number(); + int i; + my_cpu = cpu_number(); for (i=0; i < LOCK_INFO_PER_BUCKET; i++, li++) if (li->lock) { @@ -112,11 +111,11 @@ decl_simple_lock_data(, **lock) } -simple_lock(lock) +void simple_lock(lock) decl_simple_lock_data(, *lock) { - register struct lock_info *li = locate_lock_info(&lock); - register my_cpu = cpu_number(); + struct lock_info *li = locate_lock_info(&lock); + my_cpu = cpu_number(); if (current_thread()) li->stack = current_thread()->lock_stack++; @@ -131,11 +130,11 @@ decl_simple_lock_data(, *lock) li->time = time_stamp - li->time; } -simple_lock_try(lock) +int simple_lock_try(lock) decl_simple_lock_data(, *lock) { - register struct lock_info *li = locate_lock_info(&lock); - register my_cpu = cpu_number(); + struct lock_info *li = locate_lock_info(&lock); + my_cpu = cpu_number(); if (curr_ipl[my_cpu]) li->masked++; @@ -151,12 +150,12 @@ decl_simple_lock_data(, *lock) } } -simple_unlock(lock) +void simple_unlock(lock) decl_simple_lock_data(, *lock) { - register time_stamp_t stamp = time_stamp; - register time_stamp_t *time = &locate_lock_info(&lock)->time; - register unsigned *lock_stack; + time_stamp_t stamp = time_stamp; + time_stamp_t *time = &locate_lock_info(&lock)->time; + unsigned *lock_stack; *time = stamp - *time; _simple_unlock(lock); @@ -167,16 +166,13 @@ decl_simple_lock_data(, *lock) } } -lip() { +void lip(void) { lis(4, 1, 0); } #define lock_info_sort lis -unsigned scurval, ssum; -struct lock_info *sli; - -lock_info_sort(arg, abs, count) +void lock_info_sort(arg, abs, count) { struct lock_info *li, mean; int bucket = 0; @@ -215,9 +211,6 @@ lock_info_sort(arg, abs, count) sum = li->success + li->fail; if(!sum && !abs) continue; - scurval = curval; - ssum = sum; - sli = li; if (!abs) switch(arg) { case 0: break; @@ -257,7 +250,7 @@ lock_info_sort(arg, abs, count) #define lock_info_clear lic -lock_info_clear() +void lock_info_clear(void) { struct lock_info *li; int bucket = 0; @@ -271,7 +264,7 @@ lock_info_clear() memset(&default_lock_info, 0, sizeof(struct lock_info)); } -print_lock_info(li) +void print_lock_info(li) struct lock_info *li; { int off; @@ -299,11 +292,11 @@ struct lock_info *li; * Measure lock/unlock operations */ -time_lock(loops) +void time_lock(int loops) { decl_simple_lock_data(, lock) - register time_stamp_t stamp; - register int i; + time_stamp_t stamp; + int i; if (!loops) @@ -340,7 +333,7 @@ void retry_simple_lock(lock) decl_simple_lock_data(, *lock) { - register count = 0; + count = 0; while(!simple_lock_try(lock)) if (count++ > 1000000 && lock != &kdb_lock) { @@ -356,7 +349,7 @@ decl_simple_lock_data(, *lock) void retry_bit_lock(index, addr) { - register count = 0; + count = 0; while(!bit_lock_try(index, addr)) if (count++ > 1000000) { diff --git a/kern/mach_clock.c b/kern/mach_clock.c index edf87f07..b627b89d 100644 --- a/kern/mach_clock.c +++ b/kern/mach_clock.c @@ -27,7 +27,7 @@ * the rights to redistribute these changes. */ /* - * File: clock_prim.c + * File: mach_clock.c * Author: Avadis Tevanian, Jr. * Date: 1986 * @@ -54,6 +54,7 @@ #include <kern/thread.h> #include <kern/time_stamp.h> #include <kern/timer.h> +#include <kern/priority.h> #include <vm/vm_kern.h> #include <sys/time.h> #include <machine/mach_param.h> /* HZ */ @@ -64,8 +65,6 @@ #include <kern/pc_sample.h> #endif -void softclock(); /* forward */ - int hz = HZ; /* number of ticks per second */ int tick = (1000000 / HZ); /* number of usec per tick */ time_value_t time = { 0, 0 }; /* time since bootup (uncorrected) */ @@ -121,13 +120,13 @@ timer_elt_data_t timer_head; /* ordered list of timeouts */ * the accuracy of the hardware clock. * */ -void clock_interrupt(usec, usermode, basepri) - register int usec; /* microseconds per tick */ - boolean_t usermode; /* executing user code */ - boolean_t basepri; /* at base priority */ +void clock_interrupt( + int usec, /* microseconds per tick */ + boolean_t usermode, /* executing user code */ + boolean_t basepri) /* at base priority */ { - register int my_cpu = cpu_number(); - register thread_t thread = current_thread(); + int my_cpu = cpu_number(); + thread_t thread = current_thread(); counter(c_clock_ticks++); counter(c_threads_total += c_threads_current); @@ -150,8 +149,7 @@ void clock_interrupt(usec, usermode, basepri) * Increment the CPU time statistics. */ { - extern void thread_quantum_update(); /* in priority.c */ - register int state; + int state; if (usermode) state = CPU_STATE_USER; @@ -187,8 +185,8 @@ void clock_interrupt(usec, usermode, basepri) */ if (my_cpu == master_cpu) { - register spl_t s; - register timer_elt_t telt; + spl_t s; + timer_elt_t telt; boolean_t needsoft = FALSE; #if TS_FORMAT == 1 @@ -221,7 +219,7 @@ void clock_interrupt(usec, usermode, basepri) time_value_add_usec(&time, usec); } else { - register int delta; + int delta; if (timedelta < 0) { delta = usec - tickdelta; @@ -236,7 +234,7 @@ void clock_interrupt(usec, usermode, basepri) update_mapped_time(&time); /* - * Schedule soft-interupt for timeout if needed + * Schedule soft-interrupt for timeout if needed */ if (needsoft) { if (basepri) { @@ -272,15 +270,15 @@ void clock_interrupt(usec, usermode, basepri) * and corrupts it. */ -void softclock() +void softclock(void) { /* * Handle timeouts. */ spl_t s; - register timer_elt_t telt; - register void (*fcn)( void * param ); - register void *param; + timer_elt_t telt; + void (*fcn)( void * param ); + void *param; while (TRUE) { s = splsched(); @@ -311,12 +309,12 @@ void softclock() * telt timer element. Function and param are already set. * interval time-out interval, in hz. */ -void set_timeout(telt, interval) - register timer_elt_t telt; /* already loaded */ - register unsigned int interval; +void set_timeout( + timer_elt_t telt, /* already loaded */ + unsigned int interval) { spl_t s; - register timer_elt_t next; + timer_elt_t next; s = splsched(); simple_lock(&timer_lock); @@ -341,8 +339,7 @@ void set_timeout(telt, interval) splx(s); } -boolean_t reset_timeout(telt) - register timer_elt_t telt; +boolean_t reset_timeout(timer_elt_t telt) { spl_t s; @@ -362,7 +359,7 @@ boolean_t reset_timeout(telt) } } -void init_timeout() +void init_timeout(void) { simple_lock_init(&timer_lock); queue_init(&timer_head.chain); @@ -389,7 +386,7 @@ record_time_stamp (time_value_t *stamp) */ kern_return_t host_get_time(host, current_time) - host_t host; + const host_t host; time_value_t *current_time; /* OUT */ { if (host == HOST_NULL) @@ -408,7 +405,7 @@ host_get_time(host, current_time) */ kern_return_t host_set_time(host, new_time) - host_t host; + const host_t host; time_value_t new_time; { spl_t s; @@ -446,7 +443,7 @@ host_set_time(host, new_time) */ kern_return_t host_adjust_time(host, new_adjustment, old_adjustment) - host_t host; + const host_t host; time_value_t new_adjustment; time_value_t *old_adjustment; /* OUT */ { @@ -492,7 +489,7 @@ host_adjust_time(host, new_adjustment, old_adjustment) return (KERN_SUCCESS); } -void mapable_time_init() +void mapable_time_init(void) { if (kmem_alloc_wired(kernel_map, (vm_offset_t *) &mtime, PAGE_SIZE) != KERN_SUCCESS) @@ -501,13 +498,13 @@ void mapable_time_init() update_mapped_time(&time); } -int timeopen() +int timeopen(dev_t dev, int flag, io_req_t ior) { return(0); } -int timeclose() +void timeclose(dev_t dev, int flag) { - return(0); + return; } /* @@ -528,13 +525,13 @@ timer_elt_data_t timeout_timers[NTIMERS]; * param: parameter to pass to function * interval: timeout interval, in hz. */ -void timeout(fcn, param, interval) - void (*fcn)( void * param ); - void * param; - int interval; +void timeout( + void (*fcn)(void *param), + void * param, + int interval) { spl_t s; - register timer_elt_t elt; + timer_elt_t elt; s = splsched(); simple_lock(&timer_lock); @@ -557,11 +554,11 @@ void timeout(fcn, param, interval) * and removed. */ boolean_t untimeout(fcn, param) - register void (*fcn)( void * param ); - register void * param; + void (*fcn)( void * param ); + const void * param; { spl_t s; - register timer_elt_t elt; + timer_elt_t elt; s = splsched(); simple_lock(&timer_lock); diff --git a/kern/mach_clock.h b/kern/mach_clock.h index 4e4e8ff1..89fd3352 100644 --- a/kern/mach_clock.h +++ b/kern/mach_clock.h @@ -29,6 +29,10 @@ #include <mach/time_value.h> #include <kern/host.h> #include <kern/queue.h> +#include <sys/types.h> + +struct io_req; +typedef struct io_req *io_req_t; /* Timers in kernel. */ @@ -102,6 +106,9 @@ extern void mapable_time_init (void); /* For public timer elements. */ extern void timeout(timer_func_t *fcn, void *param, int interval); -extern boolean_t untimeout(timer_func_t *fcn, void *param); +extern boolean_t untimeout(timer_func_t *fcn, const void *param); + +extern int timeopen(dev_t dev, int flag, io_req_t ior); +extern void timeclose(dev_t dev, int flag); #endif /* _KERN_MACH_CLOCK_H_ */ diff --git a/kern/mach_factor.c b/kern/mach_factor.c index 558c4a06..debce0b0 100644 --- a/kern/mach_factor.c +++ b/kern/mach_factor.c @@ -55,13 +55,13 @@ static long fract[3] = { void compute_mach_factor(void) { - register processor_set_t pset; - register processor_t processor; - register int ncpus; - register int nthreads; - register long factor_now; - register long average_now; - register long load_now; + processor_set_t pset; + processor_t processor; + int ncpus; + int nthreads; + long factor_now; + long average_now; + long load_now; simple_lock(&all_psets_lock); pset = (processor_set_t) queue_first(&all_psets); @@ -123,7 +123,7 @@ void compute_mach_factor(void) * And some ugly stuff to keep w happy. */ if (pset == &default_pset) { - register int i; + int i; for (i = 0; i < 3; i++) { mach_factor[i] = ( (mach_factor[i]*fract[i]) diff --git a/kern/machine.c b/kern/machine.c index c2a19b99..eced7688 100644 --- a/kern/machine.c +++ b/kern/machine.c @@ -72,12 +72,11 @@ decl_simple_lock_data(,action_lock); * Flag specified cpu as up and running. Called when a processor comes * online. */ -void cpu_up(cpu) - int cpu; +void cpu_up(int cpu) { - register struct machine_slot *ms; - register processor_t processor; - register spl_t s; + struct machine_slot *ms; + processor_t processor; + spl_t s; processor = cpu_to_processor(cpu); pset_lock(&default_pset); @@ -102,12 +101,11 @@ void cpu_up(cpu) * Flag specified cpu as down. Called when a processor is about to * go offline. */ -void cpu_down(cpu) - int cpu; +void cpu_down(int cpu) { - register struct machine_slot *ms; - register processor_t processor; - register spl_t s; + struct machine_slot *ms; + processor_t processor; + spl_t s; s = splsched(); processor = cpu_to_processor(cpu); @@ -126,8 +124,8 @@ void cpu_down(cpu) kern_return_t host_reboot(host, options) - host_t host; - int options; + const host_t host; + int options; { if (host == HOST_NULL) return (KERN_INVALID_HOST); @@ -153,11 +151,11 @@ host_reboot(host, options) * a reference. */ void -processor_request_action(processor, new_pset) -processor_t processor; -processor_set_t new_pset; +processor_request_action( + processor_t processor, + processor_set_t new_pset) { - register processor_set_t pset; + processor_set_t pset; /* * Processor must be in a processor set. Must lock its idle lock to @@ -228,10 +226,10 @@ processor_set_t new_pset; * Synchronizes with assignment completion if wait is TRUE. */ kern_return_t -processor_assign(processor, new_pset, wait) -processor_t processor; -processor_set_t new_pset; -boolean_t wait; +processor_assign( + processor_t processor, + processor_set_t new_pset, + boolean_t wait) { spl_t s; @@ -315,14 +313,11 @@ Retry: #else /* MACH_HOST */ kern_return_t -processor_assign(processor, new_pset, wait) -processor_t processor; -processor_set_t new_pset; -boolean_t wait; +processor_assign( + processor_t processor, + processor_set_t new_pset, + boolean_t wait) { -#ifdef lint - processor++; new_pset++; wait++; -#endif return KERN_FAILURE; } @@ -334,8 +329,7 @@ boolean_t wait; * with the shutdown (can be called from interrupt level). */ kern_return_t -processor_shutdown(processor) -processor_t processor; +processor_shutdown(processor_t processor) { spl_t s; @@ -364,12 +358,10 @@ processor_t processor; /* * action_thread() shuts down processors or changes their assignment. */ -void processor_doaction(); /* forward */ - -void action_thread_continue() +void action_thread_continue(void) { - register processor_t processor; - register spl_t s; + processor_t processor; + spl_t s; while (TRUE) { s = splsched(); @@ -395,7 +387,7 @@ void action_thread_continue() } } -void action_thread() +void __attribute__((noreturn)) action_thread(void) { action_thread_continue(); /*NOTREACHED*/ @@ -406,21 +398,15 @@ void action_thread() * is to schedule ourselves onto a cpu and then save our * context back into the runqs before taking out the cpu. */ -#ifdef __GNUC__ -__volatile__ -#endif -void processor_doshutdown(); /* forward */ - -void processor_doaction(processor) -register processor_t processor; +void processor_doaction(processor_t processor) { thread_t this_thread; spl_t s; - register processor_set_t pset; + processor_set_t pset; #if MACH_HOST - register processor_set_t new_pset; - register thread_t thread; - register thread_t prev_thread = THREAD_NULL; + processor_set_t new_pset; + thread_t thread; + thread_t prev_thread = THREAD_NULL; boolean_t have_pset_ref = FALSE; #endif /* MACH_HOST */ @@ -633,13 +619,10 @@ Restart_pset: * running on the processor's shutdown stack. */ -#ifdef __GNUC__ -__volatile__ -#endif void processor_doshutdown(processor) -register processor_t processor; +processor_t processor; { - register int cpu = processor->slot_num; + int cpu = processor->slot_num; timer_switch(&kernel_timer[cpu]); @@ -663,23 +646,20 @@ register processor_t processor; #else /* NCPUS > 1 */ kern_return_t -processor_assign(processor, new_pset, wait) -processor_t processor; -processor_set_t new_pset; -boolean_t wait; +processor_assign( + processor_t processor, + processor_set_t new_pset, + boolean_t wait) { -#ifdef lint - processor++; new_pset++; wait++; -#endif /* lint */ return(KERN_FAILURE); } #endif /* NCPUS > 1 */ kern_return_t -host_get_boot_info(priv_host, boot_info) - host_t priv_host; - kernel_boot_info_t boot_info; +host_get_boot_info( + host_t priv_host, + kernel_boot_info_t boot_info) { char *src = ""; diff --git a/kern/machine.h b/kern/machine.h index af2b7e91..c67213a2 100644 --- a/kern/machine.h +++ b/kern/machine.h @@ -53,6 +53,6 @@ extern kern_return_t processor_shutdown (processor_t); /* * action_thread() shuts down processors or changes their assignment. */ -extern void action_thread_continue (void); +extern void action_thread_continue (void) __attribute__((noreturn)); #endif /* _MACHINE_H_ */ diff --git a/kern/macro_help.h b/kern/macro_help.h deleted file mode 100644 index a3d156b7..00000000 --- a/kern/macro_help.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988 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: kern/macro_help.h - * - * Provide help in making lint-free macro routines - * - */ - -#ifndef _KERN_MACRO_HELP_H_ -#define _KERN_MACRO_HELP_H_ - -#if !defined(MACRO_BEGIN) - -#include <mach/boolean.h> - -#ifdef lint -boolean_t NEVER; -boolean_t ALWAYS; -#else /* lint */ -#define NEVER FALSE -#define ALWAYS TRUE -#endif /* lint */ - -#define MACRO_BEGIN ({ -#define MACRO_END }) - -#define MACRO_RETURN if (ALWAYS) return - -#endif /* !MACRO_BEGIN */ - -#endif /* _KERN_MACRO_HELP_H_ */ diff --git a/kern/macros.h b/kern/macros.h new file mode 100644 index 00000000..fb8dc5e1 --- /dev/null +++ b/kern/macros.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2009, 2010, 2013 Richard Braun. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * + * Helper macros. + */ + +#ifndef _KERN_MACROS_H +#define _KERN_MACROS_H + +#define MACRO_BEGIN ({ +#define MACRO_END }) +#define MACRO_RETURN if (1) return + +#define __QUOTE(x) #x +#define QUOTE(x) __QUOTE(x) + +#ifdef __ASSEMBLER__ +#define DECL_CONST(x, s) x +#else /* __ASSEMBLER__ */ +#define __DECL_CONST(x, s) x##s +#define DECL_CONST(x, s) __DECL_CONST(x, s) +#endif /* __ASSEMBLER__ */ + +#define STRLEN(x) (sizeof(x) - 1) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#define DIV_CEIL(n, d) (((n) + (d) - 1) / (d)) + +#define P2ALIGNED(x, a) (((x) & ((a) - 1)) == 0) +#define ISP2(x) P2ALIGNED(x, x) +#define P2ALIGN(x, a) ((x) & -(a)) +#define P2ROUND(x, a) (-(-(x) & -(a))) +#define P2END(x, a) (-(~(x) & -(a))) + +#define structof(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) + +#define alignof(x) __alignof__(x) + +#define likely(expr) __builtin_expect(!!(expr), 1) +#define unlikely(expr) __builtin_expect(!!(expr), 0) + +#define barrier() asm volatile("" : : : "memory") + +#define __noreturn __attribute__((noreturn)) +#define __aligned(x) __attribute__((aligned(x))) +#define __always_inline inline __attribute__((always_inline)) +#define __section(x) __attribute__((section(x))) +#define __packed __attribute__((packed)) +#define __alias(x) __attribute__((alias(x))) + +#define __format_printf(fmt, args) \ + __attribute__((format(printf, fmt, args))) + +#endif /* _KERN_MACROS_H */ diff --git a/kern/pc_sample.c b/kern/pc_sample.c index 57002581..fcb9d71b 100644 --- a/kern/pc_sample.c +++ b/kern/pc_sample.c @@ -43,12 +43,9 @@ typedef sampled_pc_t sampled_pcs[MAX_PC_SAMPLES]; -int pc_sampling_enabled = 0; -decl_simple_lock_data(, pc_sampling_lock) /* lock for enabling */ - void take_pc_sample( - register thread_t t, - register sample_control_t *cp, + const thread_t t, + sample_control_t *cp, sampled_pc_flavor_t flavor) { vm_offset_t pc; @@ -192,6 +189,9 @@ get_sampled_pcs( (sampled_pc_array_t)cp->buffer, (seqidx2 + 1) * sizeof(sampled_pc_t)); } + } else if (nsamples < 0) { + /* Bogus SEQNO supplied. */ + nsamples = 0; } else { /* could either be zero because of overflow, or because * we are being lied to. In either case, return nothing. @@ -244,8 +244,8 @@ task_get_sampled_pcs( kern_return_t thread_enable_pc_sampling( - thread_t thread, - int *tickp, + const thread_t thread, + const int *tickp, sampled_pc_flavor_t flavors) { return KERN_FAILURE; /* not implemented */ @@ -253,8 +253,8 @@ thread_enable_pc_sampling( kern_return_t task_enable_pc_sampling( - task_t task, - int *tickp, + const task_t task, + const int *tickp, sampled_pc_flavor_t flavors) { return KERN_FAILURE; /* not implemented */ @@ -262,36 +262,36 @@ task_enable_pc_sampling( kern_return_t thread_disable_pc_sampling( - thread_t thread, - int *samplecntp) + const thread_t thread, + const int *samplecntp) { return KERN_FAILURE; /* not implemented */ } kern_return_t task_disable_pc_sampling( - task_t task, - int *samplecntp) + const task_t task, + const int *samplecntp) { return KERN_FAILURE; /* not implemented */ } kern_return_t thread_get_sampled_pcs( - thread_t thread, - sampled_pc_seqno_t *seqnop, - sampled_pc_array_t sampled_pcs_out, - int *sampled_pcs_cntp) + const thread_t thread, + const sampled_pc_seqno_t *seqnop, + const sampled_pc_array_t sampled_pcs_out, + const int *sampled_pcs_cntp) { return KERN_FAILURE; /* not implemented */ } kern_return_t task_get_sampled_pcs( - task_t task, - sampled_pc_seqno_t *seqnop, - sampled_pc_array_t sampled_pcs_out, - int *sampled_pcs_cntp) + const task_t task, + const sampled_pc_seqno_t *seqnop, + const sampled_pc_array_t sampled_pcs_out, + const int *sampled_pcs_cntp) { return KERN_FAILURE; /* not implemented */ } diff --git a/kern/pc_sample.h b/kern/pc_sample.h index 3c64068d..4832cb9f 100644 --- a/kern/pc_sample.h +++ b/kern/pc_sample.h @@ -49,7 +49,7 @@ #include <mach/pc_sample.h> #include <mach/machine/vm_types.h> #include <kern/kern_types.h> -#include <kern/macro_help.h> +#include <kern/macros.h> /* * Control structure for sampling, included in diff --git a/kern/printf.c b/kern/printf.c index a3a771d0..50f23623 100644 --- a/kern/printf.c +++ b/kern/printf.c @@ -126,17 +126,17 @@ #define isdigit(d) ((d) >= '0' && (d) <= '9') #define Ctod(c) ((c) - '0') -#define MAXBUF (sizeof(long int) * 8) /* enough for binary */ +#define MAXBUF (sizeof(long long int) * 8) /* enough for binary */ void printnum( - register unsigned long u, - register int base, + unsigned long long u, + int base, void (*putc)( char, vm_offset_t ), vm_offset_t putc_arg) { char buf[MAXBUF]; /* build number here */ - register char * p = &buf[MAXBUF-1]; + char * p = &buf[MAXBUF-1]; static char digs[] = "0123456789abcdef"; do { @@ -151,23 +151,8 @@ void printnum( boolean_t _doprnt_truncates = FALSE; -/* printf could be called at _any_ point during system initialization, - including before printf_init() gets called from the "normal" place - in kern/startup.c. */ -boolean_t _doprnt_lock_initialized = FALSE; -decl_simple_lock_data(,_doprnt_lock) - -void printf_init(void) -{ - if (!_doprnt_lock_initialized) - { - _doprnt_lock_initialized = TRUE; - simple_lock_init(&_doprnt_lock); - } -} - void _doprnt( - register const char *fmt, + const char *fmt, va_list argp, /* character output routine */ void (*putc)( char, vm_offset_t), @@ -178,29 +163,14 @@ void _doprnt( int prec; boolean_t ladjust; char padc; - long n; - unsigned long u; + long long n; + unsigned long long u; + int have_long_long; int plus_sign; int sign_char; boolean_t altfmt, truncate; int base; - register char c; - - printf_init(); - -#if 0 - /* Make sure that we get *some* printout, no matter what */ - simple_lock(&_doprnt_lock); -#else - { - register int i = 0; - while (i < 1*1024*1024) { - if (simple_lock_try(&_doprnt_lock)) - break; - i++; - } - } -#endif + char c; while ((c = *fmt) != '\0') { if (c != '%') { @@ -218,6 +188,7 @@ void _doprnt( plus_sign = 0; sign_char = 0; altfmt = FALSE; + have_long_long = FALSE; while (TRUE) { c = *fmt; @@ -276,6 +247,10 @@ void _doprnt( if (c == 'l') c = *++fmt; /* need it if sizeof(int) < sizeof(long) */ + if (c == 'l') { + c = *++fmt; /* handle `long long' */ + have_long_long = TRUE; + } truncate = FALSE; @@ -283,11 +258,14 @@ void _doprnt( case 'b': case 'B': { - register char *p; - boolean_t any; - register int i; - - u = va_arg(argp, unsigned long); + char *p; + boolean_t any; + int i; + + if (! have_long_long) + u = va_arg(argp, unsigned long); + else + u = va_arg(argp, unsigned long long); p = va_arg(argp, char *); base = *p++; printnum(u, base, putc, putc_arg); @@ -302,7 +280,7 @@ void _doprnt( /* * Bit field */ - register int j; + int j; if (any) (*putc)(',', putc_arg); else { @@ -342,8 +320,8 @@ void _doprnt( case 's': { - register char *p; - register char *p2; + char *p; + char *p2; if (prec == -1) prec = 0x7fffffff; /* MAXINT */ @@ -431,7 +409,10 @@ void _doprnt( goto print_unsigned; print_signed: - n = va_arg(argp, long); + if (! have_long_long) + n = va_arg(argp, long); + else + n = va_arg(argp, long long); if (n >= 0) { u = n; sign_char = plus_sign; @@ -443,13 +424,16 @@ void _doprnt( goto print_num; print_unsigned: - u = va_arg(argp, unsigned long); + if (! have_long_long) + u = va_arg(argp, unsigned long); + else + u = va_arg(argp, unsigned long long); goto print_num; print_num: { char buf[MAXBUF]; /* build number here */ - register char * p = &buf[MAXBUF-1]; + char * p = &buf[MAXBUF-1]; static char digits[] = "0123456789abcdef"; char *prefix = 0; @@ -507,8 +491,6 @@ void _doprnt( } fmt++; } - - simple_unlock(&_doprnt_lock); } /* @@ -540,7 +522,7 @@ int indent = 0; void iprintf(const char *fmt, ...) { va_list listp; - register int i; + int i; for (i = indent; i > 0; ){ if (i >= 8) { @@ -567,8 +549,8 @@ sputc( char c, vm_offset_t arg) { - register char **bufp = (char **) arg; - register char *p = *bufp; + char **bufp = (char **) arg; + char *p = *bufp; *p++ = c; *bufp = p; } @@ -615,13 +597,23 @@ vsnprintf(char *buf, size_t size, const char *fmt, va_list args) return cookie.index; } +int +snprintf(char *buf, size_t size, const char *fmt, ...) +{ + int written; + va_list listp; + va_start(listp, fmt); + written = vsnprintf(buf, size, fmt, listp); + va_end(listp); + return written; +} -void safe_gets(str, maxlen) - char *str; - int maxlen; +void safe_gets( + char *str, + int maxlen) { - register char *lp; - register int c; + char *lp; + int c; char *strmax = str + maxlen - 1; /* allow space for trailing 0 */ lp = str; diff --git a/kern/printf.h b/kern/printf.h index 8b4e7606..b72640aa 100644 --- a/kern/printf.h +++ b/kern/printf.h @@ -27,22 +27,26 @@ #include <sys/types.h> #include <stdarg.h> -extern void printf_init (void); - extern void _doprnt (const char *fmt, va_list argp, void (*putc)(char, vm_offset_t), int radix, vm_offset_t putc_arg); -extern void printnum (unsigned long u, int base, +extern void printnum (unsigned long long u, int base, void (*putc)(char, vm_offset_t), vm_offset_t putc_arg); -extern int sprintf (char *buf, const char *fmt, ...); -extern int vsnprintf (char *buf, size_t size, const char *fmt, va_list args); +extern int sprintf (char *buf, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int snprintf (char *buf, size_t size, const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); +extern int vsnprintf (char *buf, size_t size, const char *fmt, va_list args) + __attribute__ ((format (printf, 3, 0))); + -extern int printf (const char *fmt, ...); +extern int printf (const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); #define printf_once(fmt, ...) \ MACRO_BEGIN \ diff --git a/kern/priority.c b/kern/priority.c index 17541b8b..587ea2f9 100644 --- a/kern/priority.c +++ b/kern/priority.c @@ -27,7 +27,7 @@ * the rights to redistribute these changes. */ /* - * File: clock_prim.c + * File: priority.c * Author: Avadis Tevanian, Jr. * Date: 1986 * @@ -74,16 +74,16 @@ * Called only from clock_interrupt(). */ -void thread_quantum_update(mycpu, thread, nticks, state) - register int mycpu; - register thread_t thread; - int nticks; - int state; +void thread_quantum_update( + int mycpu, + thread_t thread, + int nticks, + int state) { - register int quantum; - register processor_t myprocessor; + int quantum; + processor_t myprocessor; #if NCPUS > 1 - register processor_set_t pset; + processor_set_t pset; #endif spl_t s; diff --git a/kern/priority.h b/kern/priority.h new file mode 100644 index 00000000..2da93ebe --- /dev/null +++ b/kern/priority.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Free Software Foundation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _KERN_PRIORITY_H_ +#define _KERN_PRIORITY_H_ + +extern void thread_quantum_update( + int mycpu, + thread_t thread, + int nticks, + int state); + +#endif /* _KERN_PRIORITY_H_ */ diff --git a/kern/processor.c b/kern/processor.c index 19868609..48e92731 100644 --- a/kern/processor.c +++ b/kern/processor.c @@ -66,18 +66,11 @@ processor_t master_processor; processor_t processor_ptr[NCPUS]; /* - * Forward declarations. - */ -void quantum_set(processor_set_t); -void pset_init(processor_set_t); -void processor_init(processor_t, int); - -/* * Bootstrap the processor/pset system so the scheduler can run. */ void pset_sys_bootstrap(void) { - register int i; + int i; pset_init(&default_pset); default_pset.empty = FALSE; @@ -109,8 +102,8 @@ void pset_sys_bootstrap(void) */ void pset_sys_init(void) { - register int i; - register processor_t processor; + int i; + processor_t processor; /* * Allocate the cache for processor sets. @@ -138,7 +131,7 @@ void pset_sys_init(void) */ void pset_init( - register processor_set_t pset) + processor_set_t pset) { int i; @@ -189,7 +182,7 @@ void pset_init( */ void processor_init( - register processor_t pr, + processor_t pr, int slot_num) { int i; @@ -414,14 +407,14 @@ void pset_reference( kern_return_t processor_info( - register processor_t processor, + processor_t processor, int flavor, host_t *host, processor_info_t info, natural_t *count) { - register int slot_num, state; - register processor_basic_info_t basic_info; + int slot_num, state; + processor_basic_info_t basic_info; if (processor == PROCESSOR_NULL) return KERN_INVALID_ARGUMENT; @@ -503,7 +496,7 @@ void quantum_set( processor_set_t pset) { #if NCPUS > 1 - register int i,ncpus; + int i, ncpus; ncpus = pset->processor_count; @@ -567,8 +560,8 @@ processor_set_create( kern_return_t processor_set_destroy( processor_set_t pset) { - register queue_entry_t elem; - register queue_head_t *list; + queue_entry_t elem; + queue_head_t *list; if (pset == PROCESSOR_SET_NULL || pset == &default_pset) return KERN_INVALID_ARGUMENT; @@ -647,18 +640,12 @@ processor_set_create( processor_set_t *new_set, 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) { -#ifdef lint - pset++; -#endif /* lint */ return KERN_FAILURE; } @@ -670,6 +657,8 @@ processor_get_assignment( processor_set_t *pset) { int state; + if (processor == PROCESSOR_NULL) + return KERN_INVALID_ARGUMENT; state = processor->state; if (state == PROCESSOR_SHUTDOWN || state == PROCESSOR_OFF_LINE) @@ -692,7 +681,7 @@ processor_set_info( return KERN_INVALID_ARGUMENT; if (flavor == PROCESSOR_SET_BASIC_INFO) { - register processor_set_basic_info_t basic_info; + processor_set_basic_info_t basic_info; if (*count < PROCESSOR_SET_BASIC_INFO_COUNT) return KERN_FAILURE; @@ -712,7 +701,7 @@ processor_set_info( return KERN_SUCCESS; } else if (flavor == PROCESSOR_SET_SCHED_INFO) { - register processor_set_sched_info_t sched_info; + processor_set_sched_info_t sched_info; if (*count < PROCESSOR_SET_SCHED_INFO_COUNT) return KERN_FAILURE; @@ -757,8 +746,8 @@ processor_set_max_priority( pset->max_priority = max_priority; if (change_threads) { - register queue_head_t *list; - register thread_t thread; + queue_head_t *list; + thread_t thread; list = &pset->threads; queue_iterate(list, thread, thread_t, pset_threads) { @@ -828,8 +817,8 @@ processor_set_policy_disable( pset->policies &= ~policy; if (change_threads) { - register queue_head_t *list; - register thread_t thread; + queue_head_t *list; + thread_t thread; list = &pset->threads; queue_iterate(list, thread, thread_t, pset_threads) { diff --git a/kern/processor.h b/kern/processor.h index 9a6c944b..b81526c0 100644 --- a/kern/processor.h +++ b/kern/processor.h @@ -320,4 +320,10 @@ extern kern_return_t processor_set_threads( natural_t *count); #endif +void processor_doaction(processor_t processor); +void processor_doshutdown(processor_t processor); +void quantum_set(processor_set_t pset); +void pset_init(processor_set_t pset); +void processor_init(processor_t pr, int slot_num); + #endif /* _KERN_PROCESSOR_H_ */ diff --git a/kern/profile.c b/kern/profile.c index e14d4116..55107218 100644 --- a/kern/profile.c +++ b/kern/profile.c @@ -194,7 +194,7 @@ thread_t th; * Make a request to the profile_thread by inserting * the buffer in the send queue, and wake it up. * The last buffer must be inserted at the head of the - * send queue, so the profile_thread handles it immediatly. + * send queue, so the profile_thread handles it immediately. */ if (kmem_alloc( kernel_map, &vm_buf_entry, sizeof(struct buf_to_send)) != KERN_SUCCESS) diff --git a/kern/queue.c b/kern/queue.c index 98b74c20..d9396e54 100644 --- a/kern/queue.c +++ b/kern/queue.c @@ -35,8 +35,8 @@ * Insert element at head of queue. */ void enqueue_head( - register queue_t que, - register queue_entry_t elt) + queue_t que, + queue_entry_t elt) { elt->next = que->next; elt->prev = que; @@ -48,8 +48,8 @@ void enqueue_head( * Insert element at tail of queue. */ void enqueue_tail( - register queue_t que, - register queue_entry_t elt) + queue_t que, + queue_entry_t elt) { elt->next = que; elt->prev = que->prev; @@ -61,9 +61,9 @@ void enqueue_tail( * Remove and return element at head of queue. */ queue_entry_t dequeue_head( - register queue_t que) + queue_t que) { - register queue_entry_t elt; + queue_entry_t elt; if (que->next == que) return((queue_entry_t)0); @@ -78,9 +78,9 @@ queue_entry_t dequeue_head( * Remove and return element at tail of queue. */ queue_entry_t dequeue_tail( - register queue_t que) + queue_t que) { - register queue_entry_t elt; + queue_entry_t elt; if (que->prev == que) return((queue_entry_t)0); @@ -100,7 +100,7 @@ queue_entry_t dequeue_tail( /*ARGSUSED*/ void remqueue( queue_t que, - register queue_entry_t elt) + queue_entry_t elt) { elt->next->prev = elt->prev; elt->prev->next = elt->next; @@ -111,8 +111,8 @@ void remqueue( * package. */ void insque( - register struct queue_entry *entry, - register struct queue_entry *pred) + struct queue_entry *entry, + struct queue_entry *pred) { entry->next = pred->next; entry->prev = pred; @@ -122,7 +122,7 @@ void insque( struct queue_entry *remque( - register struct queue_entry *elt) + struct queue_entry *elt) { (elt->next)->prev = elt->prev; (elt->prev)->next = elt->next; diff --git a/kern/queue.h b/kern/queue.h index 1846922a..f0b4002f 100644 --- a/kern/queue.h +++ b/kern/queue.h @@ -87,6 +87,14 @@ void remqueue(queue_t, queue_entry_t); void insque(queue_entry_t, queue_entry_t); /* + * Macro: queue_assert + * Function: + * Used by macros to assert that the given argument is a + * queue. + */ +#define queue_assert(q) (void) ((void) (q)->next, (q)->prev) + +/* * Macro: queue_init * Function: * Initialize the given queue. @@ -104,7 +112,7 @@ void insque(queue_entry_t, queue_entry_t); * queue_entry_t queue_first(q) * queue_t q; *IN* */ -#define queue_first(q) ((q)->next) +#define queue_first(q) (queue_assert(q), (q)->next) /* * Macro: queue_next @@ -114,7 +122,7 @@ void insque(queue_entry_t, queue_entry_t); * queue_entry_t queue_next(qc) * queue_t qc; */ -#define queue_next(qc) ((qc)->next) +#define queue_next(qc) (queue_assert(qc), (qc)->next) /* * Macro: queue_last @@ -124,7 +132,7 @@ void insque(queue_entry_t, queue_entry_t); * queue_entry_t queue_last(q) * queue_t q; *IN* */ -#define queue_last(q) ((q)->prev) +#define queue_last(q) (queue_assert(q), (q)->prev) /* * Macro: queue_prev @@ -134,7 +142,7 @@ void insque(queue_entry_t, queue_entry_t); * queue_entry_t queue_prev(qc) * queue_t qc; */ -#define queue_prev(qc) ((qc)->prev) +#define queue_prev(qc) (queue_assert(qc), (qc)->prev) /* * Macro: queue_end @@ -146,7 +154,8 @@ void insque(queue_entry_t, queue_entry_t); * queue_t q; * queue_entry_t qe; */ -#define queue_end(q, qe) ((q) == (qe)) +#define queue_end(q, qe) (queue_assert(q), queue_assert(qe), \ + (q) == (qe)) /* * Macro: queue_empty @@ -179,7 +188,9 @@ void insque(queue_entry_t, queue_entry_t); */ #define queue_enter(head, elt, type, field) \ { \ - register queue_entry_t prev; \ + queue_assert(head); \ + queue_assert(&(elt)->field); \ + queue_entry_t prev; \ \ prev = (head)->prev; \ if ((head) == prev) { \ @@ -206,7 +217,9 @@ void insque(queue_entry_t, queue_entry_t); */ #define queue_enter_first(head, elt, type, field) \ { \ - register queue_entry_t next; \ + queue_assert(head); \ + queue_assert(&(elt)->field); \ + queue_entry_t next; \ \ next = (head)->next; \ if ((head) == next) { \ @@ -239,7 +252,9 @@ void insque(queue_entry_t, queue_entry_t); */ #define queue_remove(head, elt, type, field) \ { \ - register queue_entry_t next, prev; \ + queue_assert(head); \ + queue_assert(&(elt)->field); \ + queue_entry_t next, prev; \ \ next = (elt)->field.next; \ prev = (elt)->field.prev; \ @@ -266,7 +281,9 @@ void insque(queue_entry_t, queue_entry_t); */ #define queue_remove_first(head, entry, type, field) \ { \ - register queue_entry_t next; \ + queue_assert(head); \ + queue_assert(&(entry)->field); \ + queue_entry_t next; \ \ (entry) = (type) ((head)->next); \ next = (entry)->field.next; \ @@ -289,7 +306,9 @@ void insque(queue_entry_t, queue_entry_t); */ #define queue_remove_last(head, entry, type, field) \ { \ - register queue_entry_t prev; \ + queue_assert(head); \ + queue_assert(&(entry)->field); \ + queue_entry_t prev; \ \ (entry) = (type) ((head)->prev); \ prev = (entry)->field.prev; \ @@ -306,6 +325,8 @@ void insque(queue_entry_t, queue_entry_t); */ #define queue_assign(to, from, type, field) \ { \ + queue_assert(&(to)->field); \ + queue_assert(&(from)->field); \ ((type)((from)->prev))->field.next = (to); \ ((type)((from)->next))->field.prev = (to); \ *to = *from; \ diff --git a/kern/rbtree.h b/kern/rbtree.h index 5a65d1ef..16ef2736 100644 --- a/kern/rbtree.h +++ b/kern/rbtree.h @@ -31,13 +31,9 @@ #include <stddef.h> #include <kern/assert.h> -#include <kern/macro_help.h> -#include <kern/rbtree.h> +#include <kern/macros.h> #include <sys/types.h> -#define structof(ptr, type, member) \ - ((type *)((char *)ptr - offsetof(type, member))) - /* * Indexes of the left and right nodes in the children array of a node. */ @@ -178,8 +174,8 @@ MACRO_END * This macro performs a standard lookup to obtain the insertion point of * the given node in the tree (it is assumed that the inserted node never * compares equal to any other entry in the tree) and links the node. It - * then It then checks red-black rules violations, and rebalances the tree - * if necessary. + * then checks red-black rules violations, and rebalances the tree if + * necessary. * * Unlike rbtree_lookup(), the cmp_fn parameter must compare two complete * entries, so it is suggested to use two different comparison inline diff --git a/kern/rdxtree.c b/kern/rdxtree.c new file mode 100644 index 00000000..78868b1f --- /dev/null +++ b/kern/rdxtree.c @@ -0,0 +1,830 @@ +/* + * Copyright (c) 2011-2015 Richard Braun. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Upstream site with license notes : + * http://git.sceen.net/rbraun/librbraun.git/ + */ + +#include <kern/assert.h> +#include <kern/slab.h> +#include <mach/kern_return.h> +#include <stddef.h> +#include <string.h> + +#include "macros.h" +#include "rdxtree.h" +#include "rdxtree_i.h" + +/* XXX */ +#define CHAR_BIT 8U +#define ERR_SUCCESS KERN_SUCCESS +#define ERR_BUSY KERN_INVALID_ARGUMENT +#define ERR_NOMEM KERN_RESOURCE_SHORTAGE + +/* + * Mask applied on an entry to obtain its address. + */ +#define RDXTREE_ENTRY_ADDR_MASK (~0x3UL) + +/* + * Global properties used to shape radix trees. + */ +#define RDXTREE_RADIX 6 +#define RDXTREE_RADIX_SIZE (1UL << RDXTREE_RADIX) +#define RDXTREE_RADIX_MASK (RDXTREE_RADIX_SIZE - 1) + +#if RDXTREE_RADIX < 6 +typedef unsigned long rdxtree_bm_t; +#define rdxtree_ffs(x) __builtin_ffsl(x) +#elif RDXTREE_RADIX == 6 /* RDXTREE_RADIX < 6 */ +typedef unsigned long long rdxtree_bm_t; +#define rdxtree_ffs(x) __builtin_ffsll(x) +#else /* RDXTREE_RADIX < 6 */ +#error "radix too high" +#endif /* RDXTREE_RADIX < 6 */ + +/* + * Allocation bitmap size in bits. + */ +#define RDXTREE_BM_SIZE (sizeof(rdxtree_bm_t) * CHAR_BIT) + +/* + * Empty/full allocation bitmap words. + */ +#define RDXTREE_BM_EMPTY ((rdxtree_bm_t)0) +#define RDXTREE_BM_FULL \ + ((~(rdxtree_bm_t)0) >> (RDXTREE_BM_SIZE - RDXTREE_RADIX_SIZE)) + +/* + * These macros can be replaced by actual functions in an environment + * that provides lockless synchronization such as RCU. + */ +#define llsync_assign_ptr(ptr, value) ((ptr) = (value)) +#define llsync_read_ptr(ptr) (ptr) + +/* + * Radix tree node. + * + * The height of a tree is the number of nodes to traverse until stored + * pointers are reached. A height of 0 means the entries of a node (or the + * tree root) directly point to stored pointers. + * + * The index is valid if and only if the parent isn't NULL. + * + * Concerning the allocation bitmap, a bit is set when the node it denotes, + * or one of its children, can be used to allocate an entry. Conversely, a bit + * is clear when the matching node and all of its children have no free entry. + * + * In order to support safe lockless lookups, in particular during a resize, + * each node includes the height of its subtree, which is invariant during + * the entire node lifetime. Since the tree height does vary, it can't be + * used to determine whether the tree root is a node or a stored pointer. + * This implementation assumes that all nodes and stored pointers are at least + * 4-byte aligned, and uses the least significant bit of entries to indicate + * the pointer type. This bit is set for internal nodes, and clear for stored + * pointers so that they can be accessed from slots without conversion. + */ +struct rdxtree_node { + struct rdxtree_node *parent; + unsigned int index; + unsigned int height; + unsigned int nr_entries; + rdxtree_bm_t alloc_bm; + void *entries[RDXTREE_RADIX_SIZE]; +}; + +/* + * We allocate nodes using the slab allocator. + */ +static struct kmem_cache rdxtree_node_cache; + +void +rdxtree_cache_init(void) +{ + kmem_cache_init(&rdxtree_node_cache, "rdxtree_node", + sizeof(struct rdxtree_node), 0, NULL, NULL, NULL, 0); +} + +#ifdef RDXTREE_ENABLE_NODE_CREATION_FAILURES +unsigned int rdxtree_fail_node_creation_threshold; +unsigned int rdxtree_nr_node_creations; +#endif /* RDXTREE_ENABLE_NODE_CREATION_FAILURES */ + +static inline int +rdxtree_check_alignment(const void *ptr) +{ + return ((unsigned long)ptr & ~RDXTREE_ENTRY_ADDR_MASK) == 0; +} + +static inline void * +rdxtree_entry_addr(void *entry) +{ + return (void *)((unsigned long)entry & RDXTREE_ENTRY_ADDR_MASK); +} + +static inline int +rdxtree_entry_is_node(const void *entry) +{ + return ((unsigned long)entry & 1) != 0; +} + +static inline void * +rdxtree_node_to_entry(struct rdxtree_node *node) +{ + return (void *)((unsigned long)node | 1); +} + +static int +rdxtree_node_create(struct rdxtree_node **nodep, unsigned int height) +{ + struct rdxtree_node *node; + +#ifdef RDXTREE_ENABLE_NODE_CREATION_FAILURES + if (rdxtree_fail_node_creation_threshold != 0) { + rdxtree_nr_node_creations++; + + if (rdxtree_nr_node_creations == rdxtree_fail_node_creation_threshold) + return ERR_NOMEM; + } +#endif /* RDXTREE_ENABLE_NODE_CREATION_FAILURES */ + + node = (struct rdxtree_node *) kmem_cache_alloc(&rdxtree_node_cache); + + if (node == NULL) + return ERR_NOMEM; + + assert(rdxtree_check_alignment(node)); + node->parent = NULL; + node->height = height; + node->nr_entries = 0; + node->alloc_bm = RDXTREE_BM_FULL; + memset(node->entries, 0, sizeof(node->entries)); + *nodep = node; + return 0; +} + +static void +rdxtree_node_schedule_destruction(struct rdxtree_node *node) +{ + /* + * This function is intended to use the appropriate interface to defer + * destruction until all read-side references are dropped in an + * environment that provides lockless synchronization. + * + * Otherwise, it simply "schedules" destruction immediately. + */ + kmem_cache_free(&rdxtree_node_cache, (vm_offset_t) node); +} + +static inline void +rdxtree_node_link(struct rdxtree_node *node, struct rdxtree_node *parent, + unsigned int index) +{ + node->parent = parent; + node->index = index; +} + +static inline void +rdxtree_node_unlink(struct rdxtree_node *node) +{ + assert(node->parent != NULL); + node->parent = NULL; +} + +static inline int +rdxtree_node_full(struct rdxtree_node *node) +{ + return (node->nr_entries == ARRAY_SIZE(node->entries)); +} + +static inline int +rdxtree_node_empty(struct rdxtree_node *node) +{ + return (node->nr_entries == 0); +} + +static inline void +rdxtree_node_insert(struct rdxtree_node *node, unsigned int index, + void *entry) +{ + assert(index < ARRAY_SIZE(node->entries)); + assert(node->entries[index] == NULL); + + node->nr_entries++; + llsync_assign_ptr(node->entries[index], entry); +} + +static inline void +rdxtree_node_insert_node(struct rdxtree_node *node, unsigned int index, + struct rdxtree_node *child) +{ + rdxtree_node_insert(node, index, rdxtree_node_to_entry(child)); +} + +static inline void +rdxtree_node_remove(struct rdxtree_node *node, unsigned int index) +{ + assert(index < ARRAY_SIZE(node->entries)); + assert(node->entries[index] != NULL); + + node->nr_entries--; + llsync_assign_ptr(node->entries[index], NULL); +} + +static inline void * +rdxtree_node_find(struct rdxtree_node *node, unsigned int *indexp) +{ + unsigned int index; + void *ptr; + + index = *indexp; + + while (index < ARRAY_SIZE(node->entries)) { + ptr = rdxtree_entry_addr(llsync_read_ptr(node->entries[index])); + + if (ptr != NULL) { + *indexp = index; + return ptr; + } + + index++; + } + + return NULL; +} + +static inline void +rdxtree_node_bm_set(struct rdxtree_node *node, unsigned int index) +{ + node->alloc_bm |= (rdxtree_bm_t)1 << index; +} + +static inline void +rdxtree_node_bm_clear(struct rdxtree_node *node, unsigned int index) +{ + node->alloc_bm &= ~((rdxtree_bm_t)1 << index); +} + +static inline int +rdxtree_node_bm_is_set(struct rdxtree_node *node, unsigned int index) +{ + return (node->alloc_bm & ((rdxtree_bm_t)1 << index)); +} + +static inline int +rdxtree_node_bm_empty(struct rdxtree_node *node) +{ + return (node->alloc_bm == RDXTREE_BM_EMPTY); +} + +static inline unsigned int +rdxtree_node_bm_first(struct rdxtree_node *node) +{ + return rdxtree_ffs(node->alloc_bm) - 1; +} + +static inline rdxtree_key_t +rdxtree_max_key(unsigned int height) +{ + size_t shift; + + shift = RDXTREE_RADIX * height; + + if (likely(shift < (sizeof(rdxtree_key_t) * CHAR_BIT))) + return ((rdxtree_key_t)1 << shift) - 1; + else + return ~((rdxtree_key_t)0); +} + +static void +rdxtree_shrink(struct rdxtree *tree) +{ + struct rdxtree_node *node; + void *entry; + + while (tree->height > 0) { + node = rdxtree_entry_addr(tree->root); + + if (node->nr_entries != 1) + break; + + entry = node->entries[0]; + + if (entry == NULL) + break; + + tree->height--; + + if (tree->height > 0) + rdxtree_node_unlink(rdxtree_entry_addr(entry)); + + llsync_assign_ptr(tree->root, entry); + rdxtree_node_schedule_destruction(node); + } +} + +static int +rdxtree_grow(struct rdxtree *tree, rdxtree_key_t key) +{ + struct rdxtree_node *root, *node; + unsigned int new_height; + int error; + + new_height = tree->height + 1; + + while (key > rdxtree_max_key(new_height)) + new_height++; + + if (tree->root == NULL) { + tree->height = new_height; + return ERR_SUCCESS; + } + + root = rdxtree_entry_addr(tree->root); + + do { + error = rdxtree_node_create(&node, tree->height); + + if (error) { + rdxtree_shrink(tree); + return error; + } + + if (tree->height == 0) + rdxtree_node_bm_clear(node, 0); + else { + rdxtree_node_link(root, node, 0); + + if (rdxtree_node_bm_empty(root)) + rdxtree_node_bm_clear(node, 0); + } + + rdxtree_node_insert(node, 0, tree->root); + tree->height++; + llsync_assign_ptr(tree->root, rdxtree_node_to_entry(node)); + root = node; + } while (new_height > tree->height); + + return ERR_SUCCESS; +} + +static void +rdxtree_cleanup(struct rdxtree *tree, struct rdxtree_node *node) +{ + struct rdxtree_node *prev; + + for (;;) { + if (likely(!rdxtree_node_empty(node))) { + if (unlikely(node->parent == NULL)) + rdxtree_shrink(tree); + + break; + } + + if (node->parent == NULL) { + tree->height = 0; + llsync_assign_ptr(tree->root, NULL); + rdxtree_node_schedule_destruction(node); + break; + } + + prev = node; + node = node->parent; + rdxtree_node_unlink(prev); + rdxtree_node_remove(node, prev->index); + rdxtree_node_schedule_destruction(prev); + } +} + +static void +rdxtree_insert_bm_clear(struct rdxtree_node *node, unsigned int index) +{ + for (;;) { + rdxtree_node_bm_clear(node, index); + + if (!rdxtree_node_full(node) || (node->parent == NULL)) + break; + + index = node->index; + node = node->parent; + } +} + +int +rdxtree_insert_common(struct rdxtree *tree, rdxtree_key_t key, + void *ptr, void ***slotp) +{ + struct rdxtree_node *node, *prev; + unsigned int height, shift, index = index; + int error; + + assert(ptr != NULL); + assert(rdxtree_check_alignment(ptr)); + + if (unlikely(key > rdxtree_max_key(tree->height))) { + error = rdxtree_grow(tree, key); + + if (error) + return error; + } + + height = tree->height; + + if (unlikely(height == 0)) { + if (tree->root != NULL) + return ERR_BUSY; + + llsync_assign_ptr(tree->root, ptr); + + if (slotp != NULL) + *slotp = &tree->root; + + return ERR_SUCCESS; + } + + node = rdxtree_entry_addr(tree->root); + shift = (height - 1) * RDXTREE_RADIX; + prev = NULL; + + do { + if (node == NULL) { + error = rdxtree_node_create(&node, height - 1); + + if (error) { + if (prev == NULL) + tree->height = 0; + else + rdxtree_cleanup(tree, prev); + + return error; + } + + if (prev == NULL) + llsync_assign_ptr(tree->root, rdxtree_node_to_entry(node)); + else { + rdxtree_node_link(node, prev, index); + rdxtree_node_insert_node(prev, index, node); + } + } + + prev = node; + index = (unsigned int)(key >> shift) & RDXTREE_RADIX_MASK; + node = rdxtree_entry_addr(prev->entries[index]); + shift -= RDXTREE_RADIX; + height--; + } while (height > 0); + + if (unlikely(node != NULL)) + return ERR_BUSY; + + rdxtree_node_insert(prev, index, ptr); + rdxtree_insert_bm_clear(prev, index); + + if (slotp != NULL) + *slotp = &prev->entries[index]; + + return ERR_SUCCESS; +} + +int +rdxtree_insert_alloc_common(struct rdxtree *tree, void *ptr, + rdxtree_key_t *keyp, void ***slotp) +{ + struct rdxtree_node *node, *prev; + unsigned int height, shift, index = index; + rdxtree_key_t key; + int error; + + assert(ptr != NULL); + assert(rdxtree_check_alignment(ptr)); + + height = tree->height; + + if (unlikely(height == 0)) { + if (tree->root == NULL) { + llsync_assign_ptr(tree->root, ptr); + *keyp = 0; + + if (slotp != NULL) + *slotp = &tree->root; + + return ERR_SUCCESS; + } + + goto grow; + } + + node = rdxtree_entry_addr(tree->root); + key = 0; + shift = (height - 1) * RDXTREE_RADIX; + prev = NULL; + + do { + if (node == NULL) { + error = rdxtree_node_create(&node, height - 1); + + if (error) { + rdxtree_cleanup(tree, prev); + return error; + } + + rdxtree_node_link(node, prev, index); + rdxtree_node_insert_node(prev, index, node); + } + + prev = node; + index = rdxtree_node_bm_first(node); + + if (index == (unsigned int)-1) + goto grow; + + key |= (rdxtree_key_t)index << shift; + node = rdxtree_entry_addr(node->entries[index]); + shift -= RDXTREE_RADIX; + height--; + } while (height > 0); + + rdxtree_node_insert(prev, index, ptr); + rdxtree_insert_bm_clear(prev, index); + + if (slotp != NULL) + *slotp = &prev->entries[index]; + + goto out; + +grow: + key = rdxtree_max_key(height) + 1; + error = rdxtree_insert_common(tree, key, ptr, slotp); + + if (error) + return error; + +out: + *keyp = key; + return ERR_SUCCESS; +} + +static void +rdxtree_remove_bm_set(struct rdxtree_node *node, unsigned int index) +{ + do { + rdxtree_node_bm_set(node, index); + + if (node->parent == NULL) + break; + + index = node->index; + node = node->parent; + } while (!rdxtree_node_bm_is_set(node, index)); +} + +void * +rdxtree_remove(struct rdxtree *tree, rdxtree_key_t key) +{ + struct rdxtree_node *node, *prev; + unsigned int height, shift, index; + + height = tree->height; + + if (unlikely(key > rdxtree_max_key(height))) + return NULL; + + node = rdxtree_entry_addr(tree->root); + + if (unlikely(height == 0)) { + llsync_assign_ptr(tree->root, NULL); + return node; + } + + shift = (height - 1) * RDXTREE_RADIX; + + do { + if (node == NULL) + return NULL; + + prev = node; + index = (unsigned int)(key >> shift) & RDXTREE_RADIX_MASK; + node = rdxtree_entry_addr(node->entries[index]); + shift -= RDXTREE_RADIX; + height--; + } while (height > 0); + + if (node == NULL) + return NULL; + + rdxtree_node_remove(prev, index); + rdxtree_remove_bm_set(prev, index); + rdxtree_cleanup(tree, prev); + return node; +} + +void * +rdxtree_lookup_common(const struct rdxtree *tree, rdxtree_key_t key, + int get_slot) +{ + struct rdxtree_node *node, *prev; + unsigned int height, shift, index; + void *entry; + + entry = llsync_read_ptr(tree->root); + + if (entry == NULL) { + node = NULL; + height = 0; + } else { + node = rdxtree_entry_addr(entry); + height = rdxtree_entry_is_node(entry) ? node->height + 1 : 0; + } + + if (key > rdxtree_max_key(height)) + return NULL; + + if (height == 0) { + if (node == NULL) + return NULL; + + return get_slot ? (void *)&tree->root : node; + } + + shift = (height - 1) * RDXTREE_RADIX; + + do { + if (node == NULL) + return NULL; + + prev = node; + index = (unsigned int)(key >> shift) & RDXTREE_RADIX_MASK; + entry = llsync_read_ptr(node->entries[index]); + node = rdxtree_entry_addr(entry); + shift -= RDXTREE_RADIX; + height--; + } while (height > 0); + + if (node == NULL) + return NULL; + + return get_slot ? (void *)&prev->entries[index] : node; +} + +void * +rdxtree_replace_slot(void **slot, void *ptr) +{ + void *old; + + assert(ptr != NULL); + assert(rdxtree_check_alignment(ptr)); + + old = *slot; + assert(old != NULL); + assert(rdxtree_check_alignment(old)); + llsync_assign_ptr(*slot, ptr); + return old; +} + +static void * +rdxtree_walk_next(struct rdxtree *tree, struct rdxtree_iter *iter) +{ + struct rdxtree_node *root, *node, *prev; + unsigned int height, shift, index, orig_index; + rdxtree_key_t key; + void *entry; + + entry = llsync_read_ptr(tree->root); + + if (entry == NULL) + return NULL; + + if (!rdxtree_entry_is_node(entry)) { + if (iter->key != (rdxtree_key_t)-1) + return NULL; + else { + iter->key = 0; + return rdxtree_entry_addr(entry); + } + } + + key = iter->key + 1; + + if ((key == 0) && (iter->node != NULL)) + return NULL; + + root = rdxtree_entry_addr(entry); + +restart: + node = root; + height = root->height + 1; + + if (key > rdxtree_max_key(height)) + return NULL; + + shift = (height - 1) * RDXTREE_RADIX; + + do { + prev = node; + index = (key >> shift) & RDXTREE_RADIX_MASK; + orig_index = index; + node = rdxtree_node_find(node, &index); + + if (node == NULL) { + shift += RDXTREE_RADIX; + key = ((key >> shift) + 1) << shift; + + if (key == 0) + return NULL; + + goto restart; + } + + if (orig_index != index) + key = ((key >> shift) + (index - orig_index)) << shift; + + shift -= RDXTREE_RADIX; + height--; + } while (height > 0); + + iter->node = prev; + iter->key = key; + return node; +} + +void * +rdxtree_walk(struct rdxtree *tree, struct rdxtree_iter *iter) +{ + unsigned int index, orig_index; + void *ptr; + + if (iter->node == NULL) + return rdxtree_walk_next(tree, iter); + + index = (iter->key + 1) & RDXTREE_RADIX_MASK; + + if (index != 0) { + orig_index = index; + ptr = rdxtree_node_find(iter->node, &index); + + if (ptr != NULL) { + iter->key += (index - orig_index) + 1; + return ptr; + } + } + + return rdxtree_walk_next(tree, iter); +} + +void +rdxtree_remove_all(struct rdxtree *tree) +{ + struct rdxtree_node *node, *parent; + struct rdxtree_iter iter; + + if (tree->height == 0) { + if (tree->root != NULL) + llsync_assign_ptr(tree->root, NULL); + + return; + } + + for (;;) { + rdxtree_iter_init(&iter); + rdxtree_walk_next(tree, &iter); + + if (iter.node == NULL) + break; + + node = iter.node; + parent = node->parent; + + if (parent == NULL) + rdxtree_init(tree); + else { + rdxtree_node_remove(parent, node->index); + rdxtree_remove_bm_set(parent, node->index); + rdxtree_cleanup(tree, parent); + node->parent = NULL; + } + + rdxtree_node_schedule_destruction(node); + } +} diff --git a/kern/rdxtree.h b/kern/rdxtree.h new file mode 100644 index 00000000..1f8456e0 --- /dev/null +++ b/kern/rdxtree.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2011-2015 Richard Braun. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + * Radix tree. + * + * In addition to the standard insertion operation, this implementation + * can allocate keys for the caller at insertion time. + * + * Upstream site with license notes : + * http://git.sceen.net/rbraun/librbraun.git/ + */ + +#ifndef _RDXTREE_H +#define _RDXTREE_H + +#include <stddef.h> +#include <sys/types.h> + +/* + * Initialize the node cache. + */ +void rdxtree_cache_init(void); + +/* + * This macro selects between 32 or 64-bits (the default) keys. + */ +#if 0 +#define RDXTREE_KEY_32 +#endif + +#ifdef RDXTREE_KEY_32 +typedef uint32_t rdxtree_key_t; +#else /* RDXTREE_KEY_32 */ +typedef uint64_t rdxtree_key_t; +#endif /* RDXTREE_KEY_32 */ + +/* + * Radix tree. + */ +struct rdxtree; + +/* + * Radix tree iterator. + */ +struct rdxtree_iter; + +/* + * Static tree initializer. + */ +#define RDXTREE_INITIALIZER { 0, NULL } + +#include "rdxtree_i.h" + +/* + * Initialize a tree. + */ +static inline void +rdxtree_init(struct rdxtree *tree) +{ + tree->height = 0; + tree->root = NULL; +} + +/* + * Insert a pointer in a tree. + * + * The ptr parameter must not be NULL. + */ +static inline int +rdxtree_insert(struct rdxtree *tree, rdxtree_key_t key, void *ptr) +{ + return rdxtree_insert_common(tree, key, ptr, NULL); +} + +/* + * Insert a pointer in a tree and obtain its slot. + * + * The ptr and slotp parameters must not be NULL. If successful, the slot of + * the newly inserted pointer is stored at the address pointed to by the slotp + * parameter. + */ +static inline int +rdxtree_insert_slot(struct rdxtree *tree, rdxtree_key_t key, + void *ptr, void ***slotp) +{ + return rdxtree_insert_common(tree, key, ptr, slotp); +} + +/* + * Insert a pointer in a tree, for which a new key is allocated. + * + * The ptr and keyp parameters must not be NULL. The newly allocated key is + * stored at the address pointed to by the keyp parameter. + */ +static inline int +rdxtree_insert_alloc(struct rdxtree *tree, void *ptr, rdxtree_key_t *keyp) +{ + return rdxtree_insert_alloc_common(tree, ptr, keyp, NULL); +} + +/* + * Insert a pointer in a tree, for which a new key is allocated, and obtain + * its slot. + * + * The ptr, keyp and slotp parameters must not be NULL. The newly allocated + * key is stored at the address pointed to by the keyp parameter while the + * slot of the inserted pointer is stored at the address pointed to by the + * slotp parameter. + */ +static inline int +rdxtree_insert_alloc_slot(struct rdxtree *tree, void *ptr, + rdxtree_key_t *keyp, void ***slotp) +{ + return rdxtree_insert_alloc_common(tree, ptr, keyp, slotp); +} + +/* + * Remove a pointer from a tree. + * + * The matching pointer is returned if successful, NULL otherwise. + */ +void * rdxtree_remove(struct rdxtree *tree, rdxtree_key_t key); + +/* + * Look up a pointer in a tree. + * + * The matching pointer is returned if successful, NULL otherwise. + */ +static inline void * +rdxtree_lookup(const struct rdxtree *tree, rdxtree_key_t key) +{ + return rdxtree_lookup_common(tree, key, 0); +} + +/* + * Look up a slot in a tree. + * + * A slot is a pointer to a stored pointer in a tree. It can be used as + * a placeholder for fast replacements to avoid multiple lookups on the same + * key. + * + * A slot for the matching pointer is returned if successful, NULL otherwise. + * + * See rdxtree_replace_slot(). + */ +static inline void ** +rdxtree_lookup_slot(const struct rdxtree *tree, rdxtree_key_t key) +{ + return rdxtree_lookup_common(tree, key, 1); +} + +/* + * Replace a pointer in a tree. + * + * The ptr parameter must not be NULL. The previous pointer is returned. + * + * See rdxtree_lookup_slot(). + */ +void * rdxtree_replace_slot(void **slot, void *ptr); + +/* + * Forge a loop to process all pointers of a tree. + */ +#define rdxtree_for_each(tree, iter, ptr) \ +for (rdxtree_iter_init(iter), ptr = rdxtree_walk(tree, iter); \ + ptr != NULL; \ + ptr = rdxtree_walk(tree, iter)) + +/* + * Return the key of the current pointer from an iterator. + */ +static inline rdxtree_key_t +rdxtree_iter_key(const struct rdxtree_iter *iter) +{ + return iter->key; +} + +/* + * Remove all pointers from a tree. + * + * The common way to destroy a tree and its pointers is to loop over all + * the pointers using rdxtree_for_each(), freeing them, then call this + * function. + */ +void rdxtree_remove_all(struct rdxtree *tree); + +#endif /* _RDXTREE_H */ diff --git a/kern/rdxtree_i.h b/kern/rdxtree_i.h new file mode 100644 index 00000000..1bd1f64a --- /dev/null +++ b/kern/rdxtree_i.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013-2015 Richard Braun. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * + * Upstream site with license notes : + * http://git.sceen.net/rbraun/librbraun.git/ + */ + +#ifndef _RDXTREE_I_H +#define _RDXTREE_I_H + +/* + * Radix tree. + */ +struct rdxtree { + unsigned int height; + void *root; +}; + +/* + * Radix tree iterator. + * + * The node member refers to the node containing the current pointer, if any. + * The key member refers to the current pointer, and is valid if and only if + * rdxtree_walk() has been called at least once on the iterator. + */ +struct rdxtree_iter { + void *node; + rdxtree_key_t key; +}; + +/* + * Initialize an iterator. + */ +static inline void +rdxtree_iter_init(struct rdxtree_iter *iter) +{ + iter->node = NULL; + iter->key = (rdxtree_key_t)-1; +} + +int rdxtree_insert_common(struct rdxtree *tree, rdxtree_key_t key, + void *ptr, void ***slotp); + +int rdxtree_insert_alloc_common(struct rdxtree *tree, void *ptr, + rdxtree_key_t *keyp, void ***slotp); + +void * rdxtree_lookup_common(const struct rdxtree *tree, rdxtree_key_t key, + int get_slot); + +void * rdxtree_walk(struct rdxtree *tree, struct rdxtree_iter *iter); + +#endif /* _RDXTREE_I_H */ diff --git a/kern/refcount.h b/kern/refcount.h index 7fd6cdfb..f32feb87 100644 --- a/kern/refcount.h +++ b/kern/refcount.h @@ -27,9 +27,7 @@ #ifndef _KERN_REFCOUNT_H_ #define _KERN_REFCOUNT_H_ -#include <kern/macro_help.h> - -#include "refcount.h" /*XXX*/ +#include <kern/macros.h> /* Unless the above include file specified otherwise, use the system-independent (unoptimized) atomic reference counter. */ @@ -65,6 +63,6 @@ typedef struct RefCount RefCount; if (new_value == 0) { func; } \ MACRO_END -#endif +#endif /* MACHINE_REFCOUNT */ -#endif _KERN_REFCOUNT_H_ +#endif /* _KERN_REFCOUNT_H_ */ diff --git a/kern/sched.h b/kern/sched.h index 434e0228..f82f9f56 100644 --- a/kern/sched.h +++ b/kern/sched.h @@ -38,7 +38,7 @@ #include <kern/queue.h> #include <kern/lock.h> #include <kern/kern_types.h> -#include <kern/macro_help.h> +#include <kern/macros.h> #if MACH_FIXPRI #include <mach/policy.h> @@ -60,7 +60,7 @@ #include <machine/sched_param.h> #endif /* STAT_TIME */ -#define NRQS 32 /* 32 run queues per cpu */ +#define NRQS 50 /* 50 run queues per cpu */ struct run_queue { queue_head_t runq[NRQS]; /* one for each priority */ @@ -118,7 +118,7 @@ extern int min_quantum; /* defines max context switch rate */ * Default base priorities for threads. */ #define BASEPRI_SYSTEM 6 -#define BASEPRI_USER 12 +#define BASEPRI_USER 25 /* * Macro to check for invalid priorities. @@ -153,7 +153,7 @@ extern unsigned sched_tick; #define thread_timer_delta(thread) \ MACRO_BEGIN \ - register unsigned delta; \ + unsigned delta; \ \ delta = 0; \ TIMER_DELTA((thread)->system_timer, \ diff --git a/kern/sched_prim.c b/kern/sched_prim.c index ba2dc8ab..e8f260e3 100644 --- a/kern/sched_prim.c +++ b/kern/sched_prim.c @@ -44,7 +44,7 @@ #include <kern/lock.h> #include <kern/mach_clock.h> #include <kern/mach_factor.h> -#include <kern/macro_help.h> +#include <kern/macros.h> #include <kern/processor.h> #include <kern/queue.h> #include <kern/sched.h> @@ -70,18 +70,8 @@ int sched_usec; thread_t sched_thread_id; -void set_pri(thread_t, int, boolean_t); -void do_thread_scan(void); - -thread_t choose_pset_thread(); - timer_elt_data_t recompute_priorities_timer; -#if DEBUG -void checkrq(run_queue_t, char *); -void thread_check(thread_t, run_queue_t); -#endif - /* * State machine * @@ -150,7 +140,7 @@ decl_simple_lock_data(, wait_lock[NUMQUEUES]) void wait_queue_init(void) { - register int i; + int i; for (i = 0; i < NUMQUEUES; i++) { queue_init(&wait_queue[i]); @@ -165,7 +155,7 @@ void sched_init(void) min_quantum = hz / 10; /* context switch 10 times/second */ wait_queue_init(); - pset_sys_bootstrap(); /* initialize processer mgmt. */ + pset_sys_bootstrap(); /* initialize processor mgmt. */ queue_init(&action_queue); simple_lock_init(&action_lock); sched_tick = 0; @@ -199,8 +189,8 @@ void thread_timeout( void thread_set_timeout( int t) /* timeout interval in ticks */ { - register thread_t thread = current_thread(); - register spl_t s; + thread_t thread = current_thread(); + spl_t s; s = splsched(); thread_lock(thread); @@ -215,7 +205,7 @@ void thread_set_timeout( * Set up thread timeout element when thread is created. */ void thread_timeout_setup( - register thread_t thread) + thread_t thread) { thread->timer.fcn = thread_timeout; thread->timer.param = thread; @@ -233,12 +223,10 @@ void assert_wait( event_t event, boolean_t interruptible) { - register queue_t q; - register int index; - register thread_t thread; -#if MACH_SLOCKS - register simple_lock_t lock; -#endif /* MACH_SLOCKS */ + queue_t q; + int index; + thread_t thread; + decl_simple_lock_data( , *lock); spl_t s; thread = current_thread(); @@ -250,12 +238,10 @@ void assert_wait( if (event != 0) { index = wait_hash(event); q = &wait_queue[index]; -#if MACH_SLOCKS lock = &wait_lock[index]; -#endif /* MACH_SLOCKS */ simple_lock(lock); thread_lock(thread); - enqueue_tail(q, (queue_entry_t) thread); + enqueue_tail(q, &(thread->links)); thread->wait_event = event; if (interruptible) thread->state |= TH_WAIT; @@ -288,16 +274,14 @@ void assert_wait( * interruptible. */ void clear_wait( - register thread_t thread, + thread_t thread, int result, boolean_t interrupt_only) { - register int index; - register queue_t q; -#if MACH_SLOCKS - register simple_lock_t lock; -#endif /* MACH_SLOCKS */ - register event_t event; + int index; + queue_t q; + decl_simple_lock_data( , *lock); + event_t event; spl_t s; s = splsched(); @@ -316,9 +300,7 @@ void clear_wait( thread_unlock(thread); index = wait_hash(event); q = &wait_queue[index]; -#if MACH_SLOCKS lock = &wait_lock[index]; -#endif /* MACH_SLOCKS */ simple_lock(lock); /* * If the thread is still waiting on that event, @@ -335,7 +317,7 @@ void clear_wait( simple_unlock(lock); } if (event == 0) { - register int state = thread->state; + int state = thread->state; reset_timeout_check(&thread->timer); @@ -376,7 +358,7 @@ void clear_wait( } static inline void __attribute__((noreturn)) -state_panic(thread_t thread, const char *caller) +state_panic(const thread_t thread, const char *caller) { panic ("%s: thread %x has unexpected state %x", caller, thread, thread->state); @@ -394,21 +376,17 @@ void thread_wakeup_prim( boolean_t one_thread, int result) { - register queue_t q; - register int index; - register thread_t thread, next_th; -#if MACH_SLOCKS - register simple_lock_t lock; -#endif /* MACH_SLOCKS */ + queue_t q; + int index; + thread_t thread, next_th; + decl_simple_lock_data( , *lock); spl_t s; - register int state; + int state; index = wait_hash(event); q = &wait_queue[index]; s = splsched(); -#if MACH_SLOCKS lock = &wait_lock[index]; -#endif /* MACH_SLOCKS */ simple_lock(lock); thread = (thread_t) queue_first(q); while (!queue_end(q, (queue_entry_t)thread)) { @@ -490,8 +468,8 @@ void thread_sleep( * xxx - DO NOT export this to users. */ void thread_bind( - register thread_t thread, - processor_t processor) + thread_t thread, + processor_t processor) { spl_t s; @@ -509,9 +487,9 @@ void thread_bind( */ thread_t thread_select( - register processor_t myprocessor) + processor_t myprocessor) { - register thread_t thread; + thread_t thread; myprocessor->first_quantum = TRUE; /* @@ -523,7 +501,7 @@ thread_t thread_select( myprocessor->quantum = min_quantum; } else { - register processor_set_t pset; + processor_set_t pset; #if MACH_HOST pset = myprocessor->processor_set; @@ -559,7 +537,7 @@ thread_t thread_select( } } else { - register queue_t q; + queue_t q; /* * If there is a thread at hint, grab it, @@ -622,9 +600,9 @@ thread_t thread_select( */ boolean_t thread_invoke( - register thread_t old_thread, - continuation_t continuation, - register thread_t new_thread) + thread_t old_thread, + continuation_t continuation, + thread_t new_thread) { /* * Check for invoking the same thread. @@ -637,7 +615,7 @@ boolean_t thread_invoke( thread_lock(new_thread); new_thread->state &= ~TH_UNINT; thread_unlock(new_thread); - thread_wakeup(&new_thread->state); + thread_wakeup(TH_EV_STATE(new_thread)); if (continuation != (void (*)()) 0) { (void) spl0(); @@ -659,7 +637,7 @@ boolean_t thread_invoke( new_thread->state &= ~(TH_SWAPPED | TH_UNINT); thread_unlock(new_thread); - thread_wakeup(&new_thread->state); + thread_wakeup(TH_EV_STATE(new_thread)); #if NCPUS > 1 new_thread->last_processor = current_processor(); @@ -698,7 +676,7 @@ boolean_t thread_invoke( if (old_thread->wake_active) { old_thread->wake_active = FALSE; thread_unlock(old_thread); - thread_wakeup((event_t)&old_thread->wake_active); + thread_wakeup(TH_EV_WAKE_ACTIVE(old_thread)); goto after_old_thread; } @@ -748,7 +726,7 @@ boolean_t thread_invoke( * running out of stack. */ - counter_always(c_thread_invoke_hits++); + counter(c_thread_invoke_hits++); (void) spl0(); call_continuation(new_thread->swap_func); /*NOTREACHED*/ @@ -760,7 +738,7 @@ boolean_t thread_invoke( */ thread_swapin(new_thread); thread_unlock(new_thread); - counter_always(c_thread_invoke_misses++); + counter(c_thread_invoke_misses++); return FALSE; case 0: @@ -781,7 +759,7 @@ boolean_t thread_invoke( { thread_swapin(new_thread); thread_unlock(new_thread); - counter_always(c_thread_invoke_misses++); + counter(c_thread_invoke_misses++); return FALSE; } } @@ -789,7 +767,7 @@ boolean_t thread_invoke( new_thread->state &= ~(TH_SWAPPED | TH_UNINT); thread_unlock(new_thread); - thread_wakeup(&new_thread->state); + thread_wakeup(TH_EV_STATE(new_thread)); /* * Thread is now interruptible. @@ -810,7 +788,7 @@ boolean_t thread_invoke( * changing address spaces. It updates active_threads. * It returns only if a continuation is not supplied. */ - counter_always(c_thread_invoke_csw++); + counter(c_thread_invoke_csw++); old_thread = switch_context(old_thread, continuation, new_thread); /* @@ -829,9 +807,9 @@ boolean_t thread_invoke( * Called at splsched. */ void thread_continue( - register thread_t old_thread) + thread_t old_thread) { - register continuation_t continuation = current_thread()->swap_func; + continuation_t continuation = current_thread()->swap_func; /* * We must dispatch the old thread and then @@ -865,9 +843,9 @@ void thread_continue( void thread_block( continuation_t continuation) { - register thread_t thread = current_thread(); - register processor_t myprocessor = cpu_to_processor(cpu_number()); - register thread_t new_thread; + thread_t thread = current_thread(); + processor_t myprocessor = cpu_to_processor(cpu_number()); + thread_t new_thread; spl_t s; check_simple_locks(); @@ -906,10 +884,10 @@ void thread_block( */ void thread_run( continuation_t continuation, - register thread_t new_thread) + thread_t new_thread) { - register thread_t thread = current_thread(); - register processor_t myprocessor = cpu_to_processor(cpu_number()); + thread_t thread = current_thread(); + processor_t myprocessor = cpu_to_processor(cpu_number()); spl_t s; check_simple_locks(); @@ -928,7 +906,7 @@ void thread_run( */ void thread_dispatch( - register thread_t thread) + thread_t thread) { /* * If we are discarding the thread's stack, we must do it @@ -954,7 +932,7 @@ void thread_dispatch( if (thread->wake_active) { thread->wake_active = FALSE; thread_unlock(thread); - thread_wakeup((event_t)&thread->wake_active); + thread_wakeup(TH_EV_WAKE_ACTIVE(thread)); return; } break; @@ -1020,7 +998,7 @@ shift_data_t wait_shift[32] = { (pri) = (th)->priority /* start with base priority */ \ + ((th)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT)) \ + ((th)->sched_usage >> (PRI_SHIFT_2 + SCHED_SHIFT)); \ - if ((pri) > 31) (pri) = 31; \ + if ((pri) > NRQS - 1) (pri) = NRQS - 1; \ MACRO_END #else /* PRI_SHIFT_2 */ #define do_priority_computation(th, pri) \ @@ -1028,7 +1006,7 @@ shift_data_t wait_shift[32] = { (pri) = (th)->priority /* start with base priority */ \ + ((th)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT)) \ - ((th)->sched_usage >> (SCHED_SHIFT - PRI_SHIFT_2)); \ - if ((pri) > 31) (pri) = 31; \ + if ((pri) > NRQS - 1) (pri) = NRQS - 1; \ MACRO_END #endif /* PRI_SHIFT_2 */ #else /* defined(PRI_SHIFT_2) */ @@ -1036,7 +1014,7 @@ shift_data_t wait_shift[32] = { MACRO_BEGIN \ (pri) = (th)->priority /* start with base priority */ \ + ((th)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT)); \ - if ((pri) > 31) (pri) = 31; \ + if ((pri) > NRQS - 1) (pri) = NRQS - 1; \ MACRO_END #endif /* defined(PRI_SHIFT_2) */ @@ -1053,10 +1031,10 @@ shift_data_t wait_shift[32] = { */ void compute_priority( - register thread_t thread, + thread_t thread, boolean_t resched) { - register int pri; + int pri; #if MACH_FIXPRI if (thread->policy == POLICY_TIMESHARE) { @@ -1085,9 +1063,9 @@ void compute_priority( */ void compute_my_priority( - register thread_t thread) + thread_t thread) { - register int temp_pri; + int temp_pri; do_priority_computation(thread,temp_pri); thread->sched_pri = temp_pri; @@ -1132,11 +1110,11 @@ void recompute_priorities(void *param) * can only be called by the thread on itself. */ void update_priority( - register thread_t thread) + thread_t thread) { - register unsigned int ticks; - register shift_t shiftp; - register int temp_pri; + unsigned int ticks; + shift_t shiftp; + int temp_pri; ticks = sched_tick - thread->sched_stamp; @@ -1196,7 +1174,7 @@ void update_priority( #if DEBUG #define run_queue_enqueue(rq, th) \ MACRO_BEGIN \ - register unsigned int whichq; \ + unsigned int whichq; \ \ whichq = (th)->sched_pri; \ if (whichq >= NRQS) { \ @@ -1206,7 +1184,7 @@ void update_priority( \ simple_lock(&(rq)->lock); /* lock the run queue */ \ checkrq((rq), "thread_setrun: before adding thread"); \ - enqueue_tail(&(rq)->runq[whichq], (queue_entry_t) (th)); \ + enqueue_tail(&(rq)->runq[whichq], &((th)->links)); \ \ if (whichq < (rq)->low || (rq)->count == 0) \ (rq)->low = whichq; /* minimize */ \ @@ -1220,7 +1198,7 @@ void update_priority( #else /* DEBUG */ #define run_queue_enqueue(rq, th) \ MACRO_BEGIN \ - register unsigned int whichq; \ + unsigned int whichq; \ \ whichq = (th)->sched_pri; \ if (whichq >= NRQS) { \ @@ -1229,7 +1207,7 @@ void update_priority( } \ \ simple_lock(&(rq)->lock); /* lock the run queue */ \ - enqueue_tail(&(rq)->runq[whichq], (queue_entry_t) (th)); \ + enqueue_tail(&(rq)->runq[whichq], &((th)->links)); \ \ if (whichq < (rq)->low || (rq)->count == 0) \ (rq)->low = whichq; /* minimize */ \ @@ -1249,13 +1227,13 @@ void update_priority( */ void thread_setrun( - register thread_t th, + thread_t th, boolean_t may_preempt) { - register processor_t processor; - register run_queue_t rq; + processor_t processor; + run_queue_t rq; #if NCPUS > 1 - register processor_set_t pset; + processor_set_t pset; #endif /* NCPUS > 1 */ /* @@ -1423,7 +1401,7 @@ void set_pri( int pri, boolean_t resched) { - register struct run_queue *rq; + struct run_queue *rq; rq = rem_runq(th); th->sched_pri = pri; @@ -1448,7 +1426,7 @@ void set_pri( struct run_queue *rem_runq( thread_t th) { - register struct run_queue *rq; + struct run_queue *rq; rq = th->runq; /* @@ -1514,10 +1492,10 @@ thread_t choose_thread( processor_t myprocessor) { thread_t th; - register queue_t q; - register run_queue_t runq; - register int i; - register processor_set_t pset; + queue_t q; + run_queue_t runq; + int i; + processor_set_t pset; runq = &myprocessor->runq; @@ -1558,13 +1536,13 @@ thread_t choose_thread( */ thread_t choose_pset_thread( - register processor_t myprocessor, + processor_t myprocessor, processor_set_t pset) { - register run_queue_t runq; - register thread_t th; - register queue_t q; - register int i; + run_queue_t runq; + thread_t th; + queue_t q; + int i; runq = &pset->runq; @@ -1640,14 +1618,14 @@ int no_dispatch_count = 0; * to execute. */ -void idle_thread_continue(void) +void __attribute__((noreturn)) idle_thread_continue(void) { - register processor_t myprocessor; - register volatile thread_t *threadp; - register volatile int *gcount; - register volatile int *lcount; - register thread_t new_thread; - register int state; + processor_t myprocessor; + volatile thread_t *threadp; + volatile int *gcount; + volatile int *lcount; + thread_t new_thread; + int state; int mycpu; spl_t s; @@ -1746,7 +1724,7 @@ retry: thread_run(idle_thread_continue, new_thread); } else if (state == PROCESSOR_IDLE) { - register processor_set_t pset; + processor_set_t pset; pset = myprocessor->processor_set; simple_lock(&pset->idle_lock); @@ -1797,14 +1775,14 @@ retry: void idle_thread(void) { - register thread_t self = current_thread(); + thread_t self = current_thread(); spl_t s; stack_privilege(self); s = splsched(); - self->priority = 31; - self->sched_pri = 31; + self->priority = NRQS-1; + self->sched_pri = NRQS-1; /* * Set the idle flag to indicate that this is an idle thread, @@ -1900,10 +1878,10 @@ boolean_t do_runq_scan( run_queue_t runq) { - register spl_t s; - register queue_t q; - register thread_t thread; - register int count; + spl_t s; + queue_t q; + thread_t thread; + int count; s = splsched(); simple_lock(&runq->lock); @@ -1964,11 +1942,11 @@ if (do_thread_scan_debug) void do_thread_scan(void) { - register spl_t s; - register boolean_t restart_needed = 0; - register thread_t thread; + spl_t s; + boolean_t restart_needed = 0; + thread_t thread; #if MACH_HOST - register processor_set_t pset; + processor_set_t pset; #endif /* MACH_HOST */ do { @@ -2012,12 +1990,12 @@ void do_thread_scan(void) #if DEBUG void checkrq( run_queue_t rq, - char *msg) + const char *msg) { - register queue_t q1; - register int i, j; - register queue_entry_t e; - register int low; + queue_t q1; + int i, j; + queue_entry_t e; + int low; low = -1; j = 0; @@ -2048,10 +2026,10 @@ void checkrq( } void thread_check( - register thread_t th, - register run_queue_t rq) + thread_t th, + run_queue_t rq) { - register unsigned int whichq; + unsigned int whichq; whichq = th->sched_pri; if (whichq >= NRQS) { diff --git a/kern/sched_prim.h b/kern/sched_prim.h index 5311d160..62698dc2 100644 --- a/kern/sched_prim.h +++ b/kern/sched_prim.h @@ -69,7 +69,7 @@ extern void thread_sleep( event_t event, simple_lock_t lock, boolean_t interruptible); -extern void thread_wakeup(); /* for function pointers */ +extern void thread_wakeup(void); /* for function pointers */ extern void thread_wakeup_prim( event_t event, boolean_t one_thread, @@ -103,7 +103,7 @@ extern boolean_t thread_handoff( thread_t old_thread, continuation_t continuation, thread_t new_thread); -extern void recompute_priorities(); +extern void recompute_priorities(void *param); extern void update_priority( thread_t thread); extern void compute_my_priority( @@ -115,7 +115,7 @@ extern void compute_priority( thread_t thread, boolean_t resched); extern void thread_timeout_setup( - register thread_t thread); + thread_t thread); /* * Routines defined as macros @@ -132,13 +132,10 @@ extern void thread_timeout_setup( * Machine-dependent code must define these functions. */ -extern void thread_bootstrap_return(void); -extern void thread_exception_return(void); -#ifdef __GNUC__ +extern void thread_bootstrap_return(void) __attribute__((noreturn)); +extern void thread_exception_return(void) __attribute__((noreturn)); extern void __attribute__((__noreturn__)) thread_syscall_return(kern_return_t); -#else -extern void thread_syscall_return(kern_return_t); -#endif + extern thread_t switch_context( thread_t old_thread, continuation_t continuation, @@ -153,7 +150,7 @@ extern void stack_handoff( * or are defined directly by machine-dependent code. */ -extern void stack_alloc( +extern kern_return_t stack_alloc( thread_t thread, void (*resume)(thread_t)); extern boolean_t stack_alloc_try( @@ -172,4 +169,16 @@ extern void stack_free( #define convert_ipc_timeout_to_ticks(millis) \ (((millis) * hz + 999) / 1000) +void set_pri(thread_t th, int pri, boolean_t resched); +void do_thread_scan(void); +thread_t choose_pset_thread(processor_t myprocessor, processor_set_t pset); + +#if DEBUG +void checkrq(run_queue_t rq, char *msg); +void thread_check(thread_t th, run_queue_t rq); +#endif /* DEBUG */ + +extern void idle_thread(void) __attribute__((noreturn)); +extern void sched_thread(void); + #endif /* _KERN_SCHED_PRIM_H_ */ diff --git a/kern/server_loop.ch b/kern/server_loop.ch deleted file mode 100644 index 409e013d..00000000 --- a/kern/server_loop.ch +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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: kern/server_loop.c - * - * A common server loop for builtin tasks. - */ - -/* - * Must define symbols for: - * SERVER_NAME String name of this module - * SERVER_LOOP Routine name for the loop - * SERVER_DISPATCH MiG function(s) to handle message - * - * Must redefine symbols for pager_server functions. - */ - -#include <kern/debug.h> -#include <kern/kalloc.h> -#include <mach/port.h> -#include <mach/message.h> -#include <vm/vm_kern.h> /* for kernel_map */ - -void SERVER_LOOP(rcv_set, max_size) -{ - register mach_msg_header_t *in_msg; - register mach_msg_header_t *out_msg; - register mach_msg_header_t *tmp_msg; - vm_offset_t messages; - mach_msg_return_t r; - - /* - * Allocate our message buffers. - */ - - messages = kalloc(2 * max_size); - if (messages == 0) - panic(SERVER_NAME); - in_msg = (mach_msg_header_t *) messages; - out_msg = (mach_msg_header_t *) (messages + max_size); - - /* - * Service loop... receive messages and process them. - */ - - for (;;) { - /* receive first message */ - - receive_msg: - r = mach_msg(in_msg, MACH_RCV_MSG, 0, max_size, rcv_set, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (r == MACH_MSG_SUCCESS) - break; - - printf("%s: receive failed, 0x%x.\n", SERVER_NAME, r); - } - - for (;;) { - /* process request message */ - - (void) SERVER_DISPATCH(in_msg, out_msg); - - /* send reply and receive next request */ - - if (out_msg->msgh_remote_port == MACH_PORT_NULL) - goto receive_msg; - - r = mach_msg(out_msg, MACH_SEND_MSG|MACH_RCV_MSG, - out_msg->msgh_size, max_size, rcv_set, - MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - if (r != MACH_MSG_SUCCESS) { - printf("%s: send/receive failed, 0x%x.\n", - SERVER_NAME, r); - goto receive_msg; - } - - /* swap message buffers */ - - tmp_msg = in_msg; in_msg = out_msg; out_msg = tmp_msg; - } -} diff --git a/kern/shuttle.h b/kern/shuttle.h index e8e574b6..0b1c2c5e 100644 --- a/kern/shuttle.h +++ b/kern/shuttle.h @@ -68,4 +68,4 @@ typedef struct Shuttle Shuttle; -#endif _KERN_SHUTTLE_H_ +#endif /* _KERN_SHUTTLE_H_ */ diff --git a/kern/slab.c b/kern/slab.c index 99d5bca3..1114cfa3 100644 --- a/kern/slab.c +++ b/kern/slab.c @@ -79,6 +79,7 @@ #include <string.h> #include <kern/assert.h> #include <kern/mach_clock.h> +#include <kern/macros.h> #include <kern/printf.h> #include <kern/slab.h> #include <kern/kalloc.h> @@ -96,7 +97,6 @@ /* * Utility macros. */ -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define P2ALIGNED(x, a) (((x) & ((a) - 1)) == 0) #define ISP2(x) P2ALIGNED(x, x) #define P2ALIGN(x, a) ((x) & -(a)) @@ -165,7 +165,7 @@ /* * Size of the VM submap from which default backend functions allocate. */ -#define KMEM_MAP_SIZE (128 * 1024 * 1024) +#define KMEM_MAP_SIZE (96 * 1024 * 1024) /* * Shift for the first kalloc cache size. @@ -289,8 +289,8 @@ vm_map_t kmem_map = &kmem_map_store; static unsigned long kmem_gc_last_tick; #define kmem_error(format, ...) \ - printf("mem: error: %s(): " format "\n", __func__, \ - ## __VA_ARGS__) + panic("mem: error: %s(): " format "\n", __func__, \ + ## __VA_ARGS__) #define kmem_warn(format, ...) \ printf("mem: warning: %s(): " format "\n", __func__, \ @@ -615,18 +615,24 @@ static inline void kmem_cpu_pool_push(struct kmem_cpu_pool *cpu_pool, void *obj) static int kmem_cpu_pool_fill(struct kmem_cpu_pool *cpu_pool, struct kmem_cache *cache) { - void *obj; + kmem_cache_ctor_t ctor; + void *buf; int i; + ctor = (cpu_pool->flags & KMEM_CF_VERIFY) ? NULL : cache->ctor; + simple_lock(&cache->lock); for (i = 0; i < cpu_pool->transfer_size; i++) { - obj = kmem_cache_alloc_from_slab(cache); + buf = kmem_cache_alloc_from_slab(cache); - if (obj == NULL) + if (buf == NULL) break; - kmem_cpu_pool_push(cpu_pool, obj); + if (ctor != NULL) + ctor(buf); + + kmem_cpu_pool_push(cpu_pool, buf); } simple_unlock(&cache->lock); @@ -656,7 +662,7 @@ static void kmem_cache_error(struct kmem_cache *cache, void *buf, int error, { struct kmem_buftag *buftag; - kmem_error("cache: %s, buffer: %p", cache->name, (void *)buf); + kmem_warn("cache: %s, buffer: %p", cache->name, (void *)buf); switch(error) { case KMEM_ERR_INVALID: @@ -696,9 +702,9 @@ static void kmem_cache_error(struct kmem_cache *cache, void *buf, int error, */ static void kmem_cache_compute_sizes(struct kmem_cache *cache, int flags) { - size_t i, buffers, buf_size, slab_size, free_slab_size, optimal_size; + size_t i, buffers, buf_size, slab_size, free_slab_size, optimal_size = 0; size_t waste, waste_min; - int embed, optimal_embed = optimal_embed; + int embed, optimal_embed = 0; buf_size = cache->buf_size; @@ -739,6 +745,7 @@ static void kmem_cache_compute_sizes(struct kmem_cache *cache, int flags) } while ((buffers < KMEM_MIN_BUFS_PER_SLAB) && (slab_size < KMEM_SLAB_SIZE_THRESHOLD)); + assert(optimal_size > 0); assert(!(flags & KMEM_CACHE_NOOFFSLAB) || optimal_embed); cache->slab_size = optimal_size; @@ -878,7 +885,7 @@ static int kmem_cache_grow(struct kmem_cache *cache) simple_lock(&cache->lock); if (slab != NULL) { - list_insert_tail(&cache->free_slabs, &slab->list_node); + list_insert_head(&cache->free_slabs, &slab->list_node); cache->nr_bufs += cache->bufs_per_slab; cache->nr_slabs++; cache->nr_free_slabs++; @@ -899,31 +906,28 @@ static void kmem_cache_reap(struct kmem_cache *cache) { struct kmem_slab *slab; struct list dead_slabs; + unsigned long nr_free_slabs; if (cache->flags & KMEM_CF_NO_RECLAIM) return; - list_init(&dead_slabs); - simple_lock(&cache->lock); - - while (!list_empty(&cache->free_slabs)) { - slab = list_first_entry(&cache->free_slabs, struct kmem_slab, - list_node); - list_remove(&slab->list_node); - list_insert(&dead_slabs, &slab->list_node); - cache->nr_bufs -= cache->bufs_per_slab; - cache->nr_slabs--; - cache->nr_free_slabs--; - } - + list_set_head(&dead_slabs, &cache->free_slabs); + list_init(&cache->free_slabs); + nr_free_slabs = cache->nr_free_slabs; + cache->nr_bufs -= cache->bufs_per_slab * nr_free_slabs; + cache->nr_slabs -= nr_free_slabs; + cache->nr_free_slabs = 0; simple_unlock(&cache->lock); while (!list_empty(&dead_slabs)) { slab = list_first_entry(&dead_slabs, struct kmem_slab, list_node); list_remove(&slab->list_node); kmem_slab_destroy(slab, cache); + nr_free_slabs--; } + + assert(nr_free_slabs == 0); } /* @@ -951,49 +955,20 @@ static void * kmem_cache_alloc_from_slab(struct kmem_cache *cache) slab->nr_refs++; cache->nr_objs++; - /* - * The slab has become complete. - */ if (slab->nr_refs == cache->bufs_per_slab) { + /* The slab has become complete */ list_remove(&slab->list_node); if (slab->nr_refs == 1) cache->nr_free_slabs--; } else if (slab->nr_refs == 1) { /* - * The slab has become partial. + * The slab has become partial. Insert the new slab at the end of + * the list to reduce fragmentation. */ list_remove(&slab->list_node); list_insert_tail(&cache->partial_slabs, &slab->list_node); cache->nr_free_slabs--; - } else if (!list_singular(&cache->partial_slabs)) { - struct list *node; - struct kmem_slab *tmp; - - /* - * The slab remains partial. If there are more than one partial slabs, - * maintain the list sorted. - */ - - assert(slab->nr_refs > 1); - - for (node = list_prev(&slab->list_node); - !list_end(&cache->partial_slabs, node); - node = list_prev(node)) { - tmp = list_entry(node, struct kmem_slab, list_node); - - if (tmp->nr_refs >= slab->nr_refs) - break; - } - - /* - * If the direct neighbor was found, the list is already sorted. - * If no slab was found, the slab is inserted at the head of the list. - */ - if (node != list_prev(&slab->list_node)) { - list_remove(&slab->list_node); - list_insert_after(node, &slab->list_node); - } } if ((slab->nr_refs == 1) && kmem_slab_use_tree(cache->flags)) @@ -1036,54 +1011,20 @@ static void kmem_cache_free_to_slab(struct kmem_cache *cache, void *buf) slab->nr_refs--; cache->nr_objs--; - /* - * The slab has become free. - */ if (slab->nr_refs == 0) { + /* The slab has become free */ + if (kmem_slab_use_tree(cache->flags)) rbtree_remove(&cache->active_slabs, &slab->tree_node); - /* - * The slab was partial. - */ if (cache->bufs_per_slab > 1) list_remove(&slab->list_node); - list_insert_tail(&cache->free_slabs, &slab->list_node); + list_insert_head(&cache->free_slabs, &slab->list_node); cache->nr_free_slabs++; } else if (slab->nr_refs == (cache->bufs_per_slab - 1)) { - /* - * The slab has become partial. - */ - list_insert(&cache->partial_slabs, &slab->list_node); - } else if (!list_singular(&cache->partial_slabs)) { - struct list *node; - struct kmem_slab *tmp; - - /* - * The slab remains partial. If there are more than one partial slabs, - * maintain the list sorted. - */ - - assert(slab->nr_refs > 0); - - for (node = list_next(&slab->list_node); - !list_end(&cache->partial_slabs, node); - node = list_next(node)) { - tmp = list_entry(node, struct kmem_slab, list_node); - - if (tmp->nr_refs <= slab->nr_refs) - break; - } - - /* - * If the direct neighbor was found, the list is already sorted. - * If no slab was found, the slab is inserted at the tail of the list. - */ - if (node != list_next(&slab->list_node)) { - list_remove(&slab->list_node); - list_insert_before(node, &slab->list_node); - } + /* The slab has become partial */ + list_insert_head(&cache->partial_slabs, &slab->list_node); } } @@ -1295,6 +1236,7 @@ fast_free: simple_unlock(&cpu_pool->lock); kmem_cache_free(cache->cpu_pool_type->array_cache, (vm_offset_t)array); + simple_lock(&cpu_pool->lock); goto fast_free; } @@ -1305,7 +1247,9 @@ fast_free: slab_free: #endif /* SLAB_USE_CPU_POOLS */ + simple_lock(&cache->lock); kmem_cache_free_to_slab(cache, (void *)obj); + simple_unlock(&cache->lock); } void slab_collect(void) @@ -1386,7 +1330,6 @@ void kalloc_init(void) { char name[KMEM_CACHE_NAME_SIZE]; size_t i, size; - vm_offset_t min, max; size = 1 << KALLOC_FIRST_SHIFT; @@ -1508,7 +1451,7 @@ void slab_info(void) mem_usage = (cache->nr_slabs * cache->slab_size) >> 10; mem_reclaimable = (cache->nr_free_slabs * cache->slab_size) >> 10; - printf("%-19s %6lu %3luk %4lu %6lu %6lu %7luk %10luk\n", + printf("%-19s %6lu %3luk %4lu %6lu %6lu %7uk %10uk\n", cache->name, cache->obj_size, cache->slab_size >> 10, cache->bufs_per_slab, cache->nr_objs, cache->nr_bufs, mem_usage, mem_reclaimable); @@ -1526,7 +1469,7 @@ kern_return_t host_slab_info(host_t host, cache_info_array_t *infop, struct kmem_cache *cache; cache_info_t *info; unsigned int i, nr_caches; - vm_size_t info_size = info_size; + vm_size_t info_size = 0; kern_return_t kr; if (host == HOST_NULL) @@ -1560,7 +1503,7 @@ kern_return_t host_slab_info(host_t host, cache_info_array_t *infop, i = 0; list_for_each_entry(&kmem_cache_list, cache, node) { - simple_lock(&cache_lock); + simple_lock(&cache->lock); info[i].flags = ((cache->flags & KMEM_CF_NO_CPU_POOL) ? CACHE_FLAGS_NO_CPU_POOL : 0) | ((cache->flags & KMEM_CF_SLAB_EXTERNAL) diff --git a/kern/slab.h b/kern/slab.h index 47bef218..c7be1692 100644 --- a/kern/slab.h +++ b/kern/slab.h @@ -47,6 +47,7 @@ #ifndef _KERN_SLAB_H #define _KERN_SLAB_H +#include <cache.h> #include <kern/lock.h> #include <kern/list.h> #include <kern/rbtree.h> @@ -147,21 +148,20 @@ typedef vm_offset_t (*kmem_slab_alloc_fn_t)(vm_size_t); typedef void (*kmem_slab_free_fn_t)(vm_offset_t, vm_size_t); /* - * Cache name buffer size. + * Cache name buffer size. The size is chosen so that struct + * kmem_cache fits into two cache lines. The size of a cache line on + * a typical CPU is 64 bytes. */ -#define KMEM_CACHE_NAME_SIZE 32 +#define KMEM_CACHE_NAME_SIZE 24 /* * Cache of objects. * * Locking order : cpu_pool -> cache. CPU pools locking is ordered by CPU ID. * - * The partial slabs list is sorted by slab references. Slabs with a high - * number of references are placed first on the list to reduce fragmentation. - * Sorting occurs at insertion/removal of buffers in a slab. As the list - * is maintained sorted, and the number of references only changes by one, - * this is a very cheap operation in the average case and the worst (linear) - * case is very unlikely. + * Currently, SLAB_USE_CPU_POOLS is not defined. KMEM_CACHE_NAME_SIZE + * is chosen so that the struct fits into two cache lines. The first + * cache line contains all hot fields. */ struct kmem_cache { #if SLAB_USE_CPU_POOLS @@ -177,25 +177,27 @@ struct kmem_cache { struct list free_slabs; struct rbtree active_slabs; int flags; + size_t bufctl_dist; /* Distance from buffer to bufctl */ + size_t slab_size; + unsigned long bufs_per_slab; + unsigned long nr_objs; /* Number of allocated objects */ + unsigned long nr_free_slabs; + kmem_cache_ctor_t ctor; + /* All fields below are cold */ size_t obj_size; /* User-provided size */ + /* Assuming ! SLAB_USE_CPU_POOLS, here is the cacheline boundary */ size_t align; size_t buf_size; /* Aligned object size */ - size_t bufctl_dist; /* Distance from buffer to bufctl */ - size_t slab_size; size_t color; size_t color_max; - unsigned long bufs_per_slab; - unsigned long nr_objs; /* Number of allocated objects */ unsigned long nr_bufs; /* Total number of buffers */ unsigned long nr_slabs; - unsigned long nr_free_slabs; - kmem_cache_ctor_t ctor; kmem_slab_alloc_fn_t slab_alloc_fn; kmem_slab_free_fn_t slab_free_fn; char name[KMEM_CACHE_NAME_SIZE]; size_t buftag_dist; /* Distance from buffer to buftag */ size_t redzone_pad; /* Bytes from end of object to redzone word */ -}; +} __cacheline_aligned; /* * Mach-style declarations for struct kmem_cache. diff --git a/kern/startup.c b/kern/startup.c index 0c04ccf8..de21ca4a 100644 --- a/kern/startup.c +++ b/kern/startup.c @@ -39,51 +39,41 @@ #include <kern/machine.h> #include <kern/mach_factor.h> #include <kern/mach_clock.h> -#include <kern/printf.h> #include <kern/processor.h> +#include <kern/rdxtree.h> #include <kern/sched_prim.h> #include <kern/task.h> #include <kern/thread.h> #include <kern/thread_swap.h> #include <kern/timer.h> #include <kern/xpr.h> +#include <kern/bootstrap.h> #include <kern/time_stamp.h> +#include <kern/startup.h> #include <vm/vm_kern.h> #include <vm/vm_map.h> #include <vm/vm_object.h> #include <vm/vm_page.h> +#include <vm/vm_init.h> +#include <vm/vm_pageout.h> #include <machine/machspl.h> #include <machine/pcb.h> #include <machine/pmap.h> #include <machine/model_dep.h> #include <mach/version.h> +#include <device/device_init.h> - - -extern void vm_mem_init(); -extern void vm_mem_bootstrap(); -extern void init_timeout(); -extern void machine_init(); - -extern void idle_thread(); -extern void vm_pageout(); -extern void reaper_thread(); -extern void swapin_thread(); -extern void sched_thread(); - -extern void bootstrap_create(); -extern void device_service_create(); - -void cpu_launch_first_thread(); /* forward */ -void start_kernel_threads(); /* forward */ +#if MACH_KDB +#include <device/cons.h> +#endif /* MACH_KDB */ #if ! MACH_KBD -boolean_t reboot_on_panic = 1; +boolean_t reboot_on_panic = TRUE; #endif #if NCPUS > 1 -extern void start_other_cpus(); -extern void action_thread(); +#include <machine/mp_desc.h> +#include <kern/machine.h> #endif /* NCPUS > 1 */ /* XX */ @@ -96,7 +86,7 @@ extern char *kernel_cmdline; * * Assumes that master_cpu is set. */ -void setup_main() +void setup_main(void) { thread_t startup_thread; @@ -113,15 +103,15 @@ void setup_main() } #else /* MACH_KDB */ if (strstr (kernel_cmdline, "-H ")) { - reboot_on_panic = 0; + reboot_on_panic = FALSE; } #endif /* MACH_KDB */ panic_init(); - printf_init(); sched_init(); vm_mem_bootstrap(); + rdxtree_cache_init(); ipc_bootstrap(); vm_mem_init(); ipc_init(); @@ -169,7 +159,7 @@ void setup_main() * Kick off the time-out driven routines by calling * them the first time. */ - recompute_priorities(); + recompute_priorities(NULL); compute_mach_factor(); /* @@ -212,9 +202,9 @@ void setup_main() * Now running in a thread. Create the rest of the kernel threads * and the bootstrap task. */ -void start_kernel_threads() +void start_kernel_threads(void) { - register int i; + int i; /* * Create the idle threads and the other @@ -280,7 +270,7 @@ void start_kernel_threads() } #if NCPUS > 1 -void slave_main() +void slave_main(void) { cpu_launch_first_thread(THREAD_NULL); } @@ -290,10 +280,9 @@ void slave_main() * Start up the first thread on a CPU. * First thread is specified for the master CPU. */ -void cpu_launch_first_thread(th) - register thread_t th; +void cpu_launch_first_thread(thread_t th) { - register int mycpu; + int mycpu; mycpu = cpu_number(); diff --git a/kern/startup.h b/kern/startup.h new file mode 100644 index 00000000..d924d154 --- /dev/null +++ b/kern/startup.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Free Software Foundation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _KERN_STARTUP_H_ +#define _KERN_STARTUP_H_ + +#include <kern/thread.h> + +extern void setup_main(void); +void cpu_launch_first_thread(thread_t th); +void start_kernel_threads(void); + +#endif /* _KERN_STARTUP_H_ */ diff --git a/kern/strings.c b/kern/strings.c index 3676f98e..e299534a 100644 --- a/kern/strings.c +++ b/kern/strings.c @@ -50,15 +50,15 @@ * the contents are identical up to the length of s2. * It returns < 0 if the first differing character is smaller * in s1 than in s2 or if s1 is shorter than s2 and the - * contents are identical upto the length of s1. + * contents are identical up to the length of s1. */ -int +int __attribute__ ((pure)) strcmp( - register const char *s1, - register const char *s2) + const char *s1, + const char *s2) { - register unsigned int a, b; + unsigned int a, b; do { a = *s1++; @@ -80,13 +80,13 @@ strcmp( * comparison runs for at most "n" characters. */ -int +int __attribute__ ((pure)) strncmp( - register const char *s1, - register const char *s2, + const char *s1, + const char *s2, size_t n) { - register unsigned int a, b; + unsigned int a, b; while (n != 0) { a = *s1++; @@ -113,10 +113,10 @@ strncmp( char * strcpy( - register char *to, - register const char *from) + char *to, + const char *from) { - register char *ret = to; + char *ret = to; while ((*to++ = *from++) != '\0') continue; @@ -135,11 +135,11 @@ strcpy( char * strncpy( - register char *to, - register const char *from, - register size_t count) + char *to, + const char *from, + size_t count) { - register char *ret = to; + char *ret = to; while (count != 0) { count--; @@ -157,15 +157,15 @@ strncpy( /* * Abstract: - * strlen returns the number of characters in "string" preceeding + * strlen returns the number of characters in "string" preceding * the terminating null character. */ -size_t +size_t __attribute__ ((pure)) strlen( - register const char *string) + const char *string) { - register const char *ret = string; + const char *ret = string; while (*string++ != '\0') continue; diff --git a/kern/syscall_emulation.c b/kern/syscall_emulation.c index c1c3096c..95e91d55 100644 --- a/kern/syscall_emulation.c +++ b/kern/syscall_emulation.c @@ -57,7 +57,7 @@ /* * eml_init: initialize user space emulation code */ -void eml_init() +void eml_init(void) { } @@ -68,10 +68,11 @@ void eml_init() * vector. */ -void eml_task_reference(task, parent) - task_t task, parent; +void eml_task_reference( + task_t task, + task_t parent) { - register eml_dispatch_t eml; + eml_dispatch_t eml; if (parent == TASK_NULL) eml = EML_DISPATCH_NULL; @@ -94,9 +95,9 @@ void eml_task_reference(task, parent) */ void eml_task_deallocate(task) - task_t task; + const task_t task; { - register eml_dispatch_t eml; + eml_dispatch_t eml; eml = task->eml_dispatch; if (eml != EML_DISPATCH_NULL) { @@ -116,12 +117,11 @@ void eml_task_deallocate(task) * set a list of emulated system calls for this task. */ kern_return_t -task_set_emulation_vector_internal(task, vector_start, emulation_vector, - emulation_vector_count) - task_t task; - int vector_start; - emulation_vector_t emulation_vector; - unsigned int emulation_vector_count; +task_set_emulation_vector_internal( + task_t task, + int vector_start, + emulation_vector_t emulation_vector, + unsigned int emulation_vector_count) { eml_dispatch_t cur_eml, new_eml, old_eml; vm_size_t new_size; @@ -295,12 +295,11 @@ task_set_emulation_vector_internal(task, vector_start, emulation_vector, * The list is out-of-line. */ kern_return_t -task_set_emulation_vector(task, vector_start, emulation_vector, - emulation_vector_count) - task_t task; - int vector_start; - emulation_vector_t emulation_vector; - unsigned int emulation_vector_count; +task_set_emulation_vector( + task_t task, + int vector_start, + emulation_vector_t emulation_vector, + unsigned int emulation_vector_count) { kern_return_t kr; vm_offset_t emul_vector_addr; @@ -342,12 +341,11 @@ task_set_emulation_vector(task, vector_start, emulation_vector, * List is returned out-of-line. */ kern_return_t -task_get_emulation_vector(task, vector_start, emulation_vector, - emulation_vector_count) - task_t task; - int *vector_start; /* out */ - emulation_vector_t *emulation_vector; /* out */ - unsigned int *emulation_vector_count; /* out */ +task_get_emulation_vector( + task_t task, + int *vector_start, /* out */ + emulation_vector_t *emulation_vector, /* out */ + unsigned int *emulation_vector_count) /* out */ { eml_dispatch_t eml; vm_size_t vector_size, size; @@ -445,10 +443,10 @@ task_get_emulation_vector(task, vector_start, emulation_vector, * task_set_emulation: [Server Entry] * set up for user space emulation of syscalls within this task. */ -kern_return_t task_set_emulation(task, routine_entry_pt, routine_number) - task_t task; - vm_offset_t routine_entry_pt; - int routine_number; +kern_return_t task_set_emulation( + task_t task, + vm_offset_t routine_entry_pt, + int routine_number) { return task_set_emulation_vector_internal(task, routine_number, &routine_entry_pt, 1); diff --git a/kern/syscall_emulation.h b/kern/syscall_emulation.h index 501b0a83..bf20e441 100644 --- a/kern/syscall_emulation.h +++ b/kern/syscall_emulation.h @@ -33,6 +33,7 @@ #ifndef __ASSEMBLER__ #include <mach/machine/vm_types.h> #include <kern/lock.h> +#include <kern/task.h> typedef vm_offset_t eml_routine_t; @@ -56,6 +57,11 @@ typedef vm_offset_t *emulation_vector_t; /* Variable-length array */ #define EML_MOD (err_kern|err_sub(2)) #define EML_BAD_TASK (EML_MOD|0x0001) #define EML_BAD_CNT (EML_MOD|0x0002) + +extern void eml_init(void); +extern void eml_task_reference(task_t task, task_t parent); +extern void eml_task_deallocate(task_t task); + #endif /* __ASSEMBLER__ */ #endif /* _KERN_SYSCALL_EMULATION_H_ */ diff --git a/kern/syscall_subr.c b/kern/syscall_subr.c index ae2d7d73..6d23462c 100644 --- a/kern/syscall_subr.c +++ b/kern/syscall_subr.c @@ -48,8 +48,6 @@ #include <mach/policy.h> #endif /* MACH_FIXPRI */ - - /* * swtch and swtch_pri both attempt to context switch (logic in * thread_block no-ops the context switch if nothing would happen). @@ -63,12 +61,9 @@ * returned, the thread should make one more check on the * lock and then be a good citizen and really suspend. */ - -void thread_depress_priority(thread_t, mach_msg_timeout_t); - void swtch_continue(void) { - register processor_t myprocessor; + processor_t myprocessor; myprocessor = current_processor(); thread_syscall_return(myprocessor->runq.count > 0 || @@ -78,7 +73,7 @@ void swtch_continue(void) boolean_t swtch(void) { - register processor_t myprocessor; + processor_t myprocessor; #if NCPUS > 1 myprocessor = current_processor(); @@ -96,8 +91,8 @@ boolean_t swtch(void) void swtch_pri_continue(void) { - register thread_t thread = current_thread(); - register processor_t myprocessor; + thread_t thread = current_thread(); + processor_t myprocessor; if (thread->depress_priority >= 0) (void) thread_depress_abort(thread); @@ -107,15 +102,10 @@ void swtch_pri_continue(void) /*NOTREACHED*/ } -boolean_t swtch_pri(pri) - int pri; +boolean_t swtch_pri(int pri) { - register thread_t thread = current_thread(); - register processor_t myprocessor; - -#ifdef lint - pri++; -#endif /* lint */ + thread_t thread = current_thread(); + processor_t myprocessor; #if NCPUS > 1 myprocessor = current_processor(); @@ -142,7 +132,7 @@ boolean_t swtch_pri(pri) void thread_switch_continue(void) { - register thread_t cur_thread = current_thread(); + thread_t cur_thread = current_thread(); /* * Restore depressed priority @@ -161,13 +151,13 @@ void thread_switch_continue(void) * Fixed priority threads that call this get what they asked for * even if that violates priority order. */ -kern_return_t thread_switch(thread_name, option, option_time) -mach_port_t thread_name; -int option; -mach_msg_timeout_t option_time; +kern_return_t thread_switch( + mach_port_t thread_name, + int option, + mach_msg_timeout_t option_time) { - register thread_t cur_thread = current_thread(); - register processor_t myprocessor; + thread_t cur_thread = current_thread(); + processor_t myprocessor; ipc_port_t port; /* @@ -208,8 +198,8 @@ mach_msg_timeout_t option_time; * Get corresponding thread. */ if (ip_active(port) && (ip_kotype(port) == IKOT_THREAD)) { - register thread_t thread; - register spl_t s; + thread_t thread; + spl_t s; thread = (thread_t) port->ip_kobject; /* @@ -289,9 +279,9 @@ mach_msg_timeout_t option_time; * of zero will result in no timeout being scheduled. */ void -thread_depress_priority(thread, depress_time) -register thread_t thread; -mach_msg_timeout_t depress_time; +thread_depress_priority( + thread_t thread, + mach_msg_timeout_t depress_time) { unsigned int ticks; spl_t s; @@ -312,8 +302,8 @@ mach_msg_timeout_t depress_time; * sched_pri to their lowest possible values. */ thread->depress_priority = thread->priority; - thread->priority = 31; - thread->sched_pri = 31; + thread->priority = NRQS-1; + thread->sched_pri = NRQS-1; if (ticks != 0) set_timeout(&thread->depress_timer, ticks); @@ -327,8 +317,7 @@ mach_msg_timeout_t depress_time; * Timeout routine for priority depression. */ void -thread_depress_timeout(thread) -register thread_t thread; +thread_depress_timeout(thread_t thread) { spl_t s; @@ -356,8 +345,7 @@ register thread_t thread; * Prematurely abort priority depression if there is one. */ kern_return_t -thread_depress_abort(thread) -register thread_t thread; +thread_depress_abort(thread_t thread) { spl_t s; diff --git a/kern/syscall_subr.h b/kern/syscall_subr.h index a2e39205..b6b61ab2 100644 --- a/kern/syscall_subr.h +++ b/kern/syscall_subr.h @@ -37,5 +37,6 @@ extern int thread_switch(mach_port_t, int, mach_msg_timeout_t); extern void thread_depress_timeout(thread_t); extern kern_return_t thread_depress_abort(thread_t); extern void mach_print(const char *); +extern void thread_depress_priority(thread_t thread, mach_msg_timeout_t depress_time); #endif /* _KERN_SYSCALL_SUBR_H_ */ diff --git a/kern/syscall_sw.c b/kern/syscall_sw.c index 607d843e..a383e467 100644 --- a/kern/syscall_sw.c +++ b/kern/syscall_sw.c @@ -36,6 +36,8 @@ #include <mach/mach_traps.h> #include <mach/message.h> #include <kern/syscall_subr.h> +#include <kern/ipc_mig.h> +#include <kern/eventcount.h> #include <ipc/mach_port.h> @@ -56,41 +58,20 @@ * the positive numbers) are reserved for Unix. */ -int kern_invalid_debug = 0; +boolean_t kern_invalid_debug = FALSE; -mach_port_t null_port() +mach_port_t null_port(void) { if (kern_invalid_debug) SoftDebugger("null_port mach trap"); return(MACH_PORT_NULL); } -kern_return_t kern_invalid() +kern_return_t kern_invalid(void) { if (kern_invalid_debug) SoftDebugger("kern_invalid mach trap"); return(KERN_INVALID_ARGUMENT); } -extern kern_return_t syscall_vm_map(); -extern kern_return_t syscall_vm_allocate(); -extern kern_return_t syscall_vm_deallocate(); - -extern kern_return_t syscall_task_create(); -extern kern_return_t syscall_task_terminate(); -extern kern_return_t syscall_task_suspend(); -extern kern_return_t syscall_task_set_special_port(); - -extern kern_return_t syscall_mach_port_allocate(); -extern kern_return_t syscall_mach_port_deallocate(); -extern kern_return_t syscall_mach_port_insert_right(); -extern kern_return_t syscall_mach_port_allocate_name(); - -extern kern_return_t syscall_thread_depress_abort(); -extern kern_return_t evc_wait(); -extern kern_return_t evc_wait_clear(); - -extern kern_return_t syscall_device_write_request(); -extern kern_return_t syscall_device_writev_request(); - mach_trap_t mach_trap_table[] = { MACH_TRAP(kern_invalid, 0), /* 0 */ /* Unix */ MACH_TRAP(kern_invalid, 0), /* 1 */ /* Unix */ diff --git a/kern/task.c b/kern/task.c index 114dd319..b384347f 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,17 +46,19 @@ #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) { @@ -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. @@ -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 @@ -756,7 +793,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 +801,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 +809,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 +817,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 +874,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; @@ -1026,6 +1063,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 +1095,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 +1111,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 +1134,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 +1265,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; +} diff --git a/kern/task.h b/kern/task.h index 9bfea571..2a4c28fc 100644 --- a/kern/task.h +++ b/kern/task.h @@ -39,6 +39,7 @@ #include <mach/time_value.h> #include <mach/mach_param.h> #include <mach/task_info.h> +#include <mach_debug/mach_debug_types.h> #include <kern/kern_types.h> #include <kern/lock.h> #include <kern/queue.h> @@ -48,11 +49,22 @@ #include <vm/vm_types.h> #include <machine/task.h> +/* + * Task name buffer size. The size is chosen so that struct task fits + * into three cache lines. The size of a cache line on a typical CPU + * is 64 bytes. + */ +#define TASK_NAME_SIZE 32 + struct task { /* Synchronization/destruction information */ decl_simple_lock_data(,lock) /* Task's lock */ int ref_count; /* Number of references to me */ - boolean_t active; /* Task has not been terminated */ + + /* Flags */ + unsigned int active:1, /* Task has not been terminated */ + /* boolean_t */ may_assign:1, /* can assigned pset be changed? */ + assign_active:1; /* waiting for may_assign */ /* Miscellaneous */ vm_map_t map; /* Address space description */ @@ -63,8 +75,6 @@ struct task { queue_head_t thread_list; /* list of threads */ int thread_count; /* number of threads */ processor_set_t processor_set; /* processor set for new threads */ - boolean_t may_assign; /* can assigned pset be changed? */ - boolean_t assign_active; /* waiting for may_assign */ /* User-visible scheduling information */ int user_stop_count; /* outstanding stops */ @@ -111,6 +121,8 @@ struct task { natural_t cow_faults; /* copy-on-write faults counter */ natural_t messages_sent; /* messages sent counter */ natural_t messages_received; /* messages received counter */ + + char name[TASK_NAME_SIZE]; }; #define task_lock(task) simple_lock(&(task)->lock) @@ -158,6 +170,9 @@ extern kern_return_t task_assign( extern kern_return_t task_assign_default( task_t task, boolean_t assign_threads); +extern kern_return_t task_set_name( + task_t task, + kernel_debug_name_t name); extern void consider_task_collect(void); /* @@ -167,6 +182,7 @@ extern void consider_task_collect(void); extern void task_init(void); extern void task_reference(task_t); extern void task_deallocate(task_t); +extern void task_hold_locked(task_t); extern kern_return_t task_hold(task_t); extern kern_return_t task_dowait(task_t, boolean_t); extern kern_return_t task_release(task_t); diff --git a/kern/task_notify.cli b/kern/task_notify.cli new file mode 100644 index 00000000..c6c85d99 --- /dev/null +++ b/kern/task_notify.cli @@ -0,0 +1,7 @@ +/* XXX */ + +/* This is a client presentation file. */ + +#define KERNEL_USER 1 + +#include <mach/task_notify.defs> diff --git a/kern/thread.c b/kern/thread.c index 87be9231..1f47553f 100644 --- a/kern/thread.c +++ b/kern/thread.c @@ -57,9 +57,11 @@ #include <kern/slab.h> #include <kern/mach_clock.h> #include <vm/vm_kern.h> +#include <vm/vm_user.h> #include <ipc/ipc_kmsg.h> #include <ipc/ipc_port.h> #include <ipc/mach_msg.h> +#include <ipc/mach_port.h> #include <machine/machspl.h> /* for splsched */ #include <machine/pcb.h> #include <machine/thread.h> /* for MACHINE_STACK */ @@ -72,15 +74,10 @@ struct kmem_cache thread_cache; queue_head_t reaper_queue; decl_simple_lock_data(, reaper_lock) -extern void pcb_module_init(void); - /* private */ struct thread thread_template; #if MACH_DEBUG -void stack_init(vm_offset_t stack); /* forward */ -void stack_finalize(vm_offset_t stack); /* forward */ - #define STACK_MARKER 0xdeadbeefU boolean_t stack_check_usage = FALSE; decl_simple_lock_data(, stack_usage_lock) @@ -127,10 +124,6 @@ vm_offset_t stack_free_list; /* splsched only */ unsigned int stack_free_count = 0; /* splsched only */ unsigned int stack_free_limit = 1; /* patchable */ -unsigned int stack_alloc_hits = 0; /* debugging */ -unsigned int stack_alloc_misses = 0; /* debugging */ -unsigned int stack_alloc_max = 0; /* debugging */ - /* * The next field is at the base of the stack, * so the low end is left unsullied. @@ -149,7 +142,7 @@ boolean_t stack_alloc_try( thread_t thread, void (*resume)(thread_t)) { - register vm_offset_t stack; + vm_offset_t stack; stack_lock(); stack = stack_free_list; @@ -163,10 +156,10 @@ boolean_t stack_alloc_try( if (stack != 0) { stack_attach(thread, stack, resume); - stack_alloc_hits++; + counter(c_stack_alloc_hits++); return TRUE; } else { - stack_alloc_misses++; + counter(c_stack_alloc_misses++); return FALSE; } } @@ -178,7 +171,7 @@ boolean_t stack_alloc_try( * May block. */ -void stack_alloc( +kern_return_t stack_alloc( thread_t thread, void (*resume)(thread_t)) { @@ -202,15 +195,15 @@ void stack_alloc( (void) splx(s); if (stack == 0) { + kern_return_t kr; /* * Kernel stacks should be naturally aligned, * so that it is easy to find the starting/ending * addresses of a stack given an address in the middle. */ - - if (kmem_alloc_aligned(kmem_map, &stack, KERNEL_STACK_SIZE) - != KERN_SUCCESS) - panic("stack_alloc"); + kr = kmem_alloc_aligned(kmem_map, &stack, KERNEL_STACK_SIZE); + if (kr != KERN_SUCCESS) + return kr; #if MACH_DEBUG stack_init(stack); @@ -218,6 +211,7 @@ void stack_alloc( } stack_attach(thread, stack, resume); + return KERN_SUCCESS; } /* @@ -230,7 +224,7 @@ void stack_alloc( void stack_free( thread_t thread) { - register vm_offset_t stack; + vm_offset_t stack; stack = stack_detach(thread); @@ -238,8 +232,11 @@ void stack_free( stack_lock(); stack_next(stack) = stack_free_list; stack_free_list = stack; - if (++stack_free_count > stack_alloc_max) - stack_alloc_max = stack_free_count; + stack_free_count += 1; +#if MACH_COUNTERS + if (stack_free_count > c_stack_alloc_max) + c_stack_alloc_max = stack_free_count; +#endif /* MACH_COUNTERS */ stack_unlock(); } } @@ -253,7 +250,7 @@ void stack_free( void stack_collect(void) { - register vm_offset_t stack; + vm_offset_t stack; spl_t s; s = splsched(); @@ -285,7 +282,7 @@ void stack_collect(void) */ void stack_privilege( - register thread_t thread) + thread_t thread) { /* * This implementation only works for the current thread. @@ -398,11 +395,11 @@ void thread_init(void) } kern_return_t thread_create( - register task_t parent_task, + task_t parent_task, thread_t *child_thread) /* OUT */ { - register thread_t new_thread; - register processor_set_t pset; + thread_t new_thread; + processor_set_t pset; if (parent_task == TASK_NULL) return KERN_INVALID_ARGUMENT; @@ -533,7 +530,6 @@ kern_return_t thread_create( #endif /* HW_FOOTPRINT */ #if MACH_PCSAMPLE - new_thread->pc_sample.buffer = 0; new_thread->pc_sample.seqno = 0; new_thread->pc_sample.sampletypes = 0; #endif /* MACH_PCSAMPLE */ @@ -576,11 +572,11 @@ kern_return_t thread_create( unsigned int thread_deallocate_stack = 0; void thread_deallocate( - register thread_t thread) + thread_t thread) { spl_t s; - register task_t task; - register processor_set_t pset; + task_t task; + processor_set_t pset; time_value_t user_time, system_time; @@ -711,7 +707,7 @@ void thread_deallocate( } void thread_reference( - register thread_t thread) + thread_t thread) { spl_t s; @@ -745,10 +741,10 @@ void thread_reference( * since it needs a kernel stack to execute.) */ kern_return_t thread_terminate( - register thread_t thread) + thread_t thread) { - register thread_t cur_thread = current_thread(); - register task_t cur_task; + thread_t cur_thread = current_thread(); + task_t cur_task; spl_t s; if (thread == THREAD_NULL) @@ -851,6 +847,28 @@ kern_return_t thread_terminate( return KERN_SUCCESS; } +kern_return_t thread_terminate_release( + thread_t thread, + task_t task, + mach_port_t thread_name, + mach_port_t reply_port, + vm_offset_t address, + vm_size_t size) +{ + if (task == NULL) + return KERN_INVALID_ARGUMENT; + + mach_port_deallocate(task->itk_space, thread_name); + + if (reply_port != MACH_PORT_NULL) + mach_port_destroy(task->itk_space, reply_port); + + if ((address != 0) || (size != 0)) + vm_deallocate(task->map, address, size); + + return thread_terminate(thread); +} + /* * thread_force_terminate: * @@ -860,9 +878,9 @@ kern_return_t thread_terminate( */ void thread_force_terminate( - register thread_t thread) + thread_t thread) { - boolean_t deallocate_here = FALSE; + boolean_t deallocate_here; spl_t s; ipc_thread_disable(thread); @@ -902,11 +920,11 @@ thread_force_terminate( * */ kern_return_t thread_halt( - register thread_t thread, + thread_t thread, boolean_t must_halt) { - register thread_t cur_thread = current_thread(); - register kern_return_t ret; + thread_t cur_thread = current_thread(); + kern_return_t ret; spl_t s; if (thread == cur_thread) @@ -950,7 +968,7 @@ kern_return_t thread_halt( * operation can never cause a deadlock.) */ if (cur_thread->ast & AST_HALT) { - thread_wakeup_with_result((event_t)&cur_thread->wake_active, + thread_wakeup_with_result(TH_EV_WAKE_ACTIVE(cur_thread), THREAD_INTERRUPTED); thread_unlock(thread); thread_unlock(cur_thread); @@ -988,7 +1006,7 @@ kern_return_t thread_halt( */ while ((thread->ast & AST_HALT) && (!(thread->state & TH_HALTED))) { thread->wake_active = TRUE; - thread_sleep((event_t) &thread->wake_active, + thread_sleep(TH_EV_WAKE_ACTIVE(thread), simple_lock_addr(thread->lock), TRUE); if (thread->state & TH_HALTED) { @@ -1027,7 +1045,7 @@ kern_return_t thread_halt( s = splsched(); thread_lock(thread); thread_ast_clear(thread, AST_HALT); - thread_wakeup_with_result((event_t)&thread->wake_active, + thread_wakeup_with_result(TH_EV_WAKE_ACTIVE(thread), THREAD_INTERRUPTED); thread_unlock(thread); (void) splx(s); @@ -1105,7 +1123,7 @@ kern_return_t thread_halt( } } -void walking_zombie(void) +void __attribute__((noreturn)) walking_zombie(void) { panic("the zombie walks!"); } @@ -1116,7 +1134,7 @@ void walking_zombie(void) */ void thread_halt_self(void) { - register thread_t thread = current_thread(); + thread_t thread = current_thread(); spl_t s; if (thread->ast & AST_TERMINATE) { @@ -1131,7 +1149,7 @@ void thread_halt_self(void) s = splsched(); simple_lock(&reaper_lock); - enqueue_tail(&reaper_queue, (queue_entry_t) thread); + enqueue_tail(&reaper_queue, &(thread->links)); simple_unlock(&reaper_lock); thread_lock(thread); @@ -1170,7 +1188,7 @@ void thread_halt_self(void) * suspends is maintained. */ void thread_hold( - register thread_t thread) + thread_t thread) { spl_t s; @@ -1192,11 +1210,11 @@ void thread_hold( */ kern_return_t thread_dowait( - register thread_t thread, + thread_t thread, boolean_t must_halt) { - register boolean_t need_wakeup; - register kern_return_t ret = KERN_SUCCESS; + boolean_t need_wakeup; + kern_return_t ret = KERN_SUCCESS; spl_t s; if (thread == current_thread()) @@ -1266,7 +1284,7 @@ thread_dowait( * Check for failure if interrupted. */ thread->wake_active = TRUE; - thread_sleep((event_t) &thread->wake_active, + thread_sleep(TH_EV_WAKE_ACTIVE(thread), simple_lock_addr(thread->lock), TRUE); thread_lock(thread); if ((current_thread()->wait_result != THREAD_AWAKENED) && @@ -1290,13 +1308,13 @@ thread_dowait( (void) splx(s); if (need_wakeup) - thread_wakeup((event_t) &thread->wake_active); + thread_wakeup(TH_EV_WAKE_ACTIVE(thread)); return ret; } void thread_release( - register thread_t thread) + thread_t thread) { spl_t s; @@ -1315,9 +1333,9 @@ void thread_release( } kern_return_t thread_suspend( - register thread_t thread) + thread_t thread) { - register boolean_t hold; + boolean_t hold; spl_t spl; if (thread == THREAD_NULL) @@ -1328,7 +1346,7 @@ kern_return_t thread_suspend( thread_lock(thread); /* Wait for thread to get interruptible */ while (thread->state & TH_UNINT) { - assert_wait(&thread->state, TRUE); + assert_wait(TH_EV_STATE(thread), TRUE); thread_unlock(thread); thread_block(NULL); thread_lock(thread); @@ -1361,9 +1379,9 @@ kern_return_t thread_suspend( kern_return_t thread_resume( - register thread_t thread) + thread_t thread) { - register kern_return_t ret; + kern_return_t ret; spl_t s; if (thread == THREAD_NULL) @@ -1399,7 +1417,7 @@ kern_return_t thread_resume( * Return thread's machine-dependent state. */ kern_return_t thread_get_state( - register thread_t thread, + thread_t thread, int flavor, thread_state_t old_state, /* pointer to OUT array */ natural_t *old_state_count) /*IN/OUT*/ @@ -1423,7 +1441,7 @@ kern_return_t thread_get_state( * Change thread's machine-dependent state. */ kern_return_t thread_set_state( - register thread_t thread, + thread_t thread, int flavor, thread_state_t new_state, natural_t new_state_count) @@ -1444,7 +1462,7 @@ kern_return_t thread_set_state( } kern_return_t thread_info( - register thread_t thread, + thread_t thread, int flavor, thread_info_t thread_info_out, /* pointer to OUT array */ natural_t *thread_info_count) /*IN/OUT*/ @@ -1456,7 +1474,7 @@ kern_return_t thread_info( return KERN_INVALID_ARGUMENT; if (flavor == THREAD_BASIC_INFO) { - register thread_basic_info_t basic_info; + thread_basic_info_t basic_info; /* Allow *thread_info_count to be one smaller than the usual amount, because creation_time is a new member @@ -1542,7 +1560,7 @@ kern_return_t thread_info( return KERN_SUCCESS; } else if (flavor == THREAD_SCHED_INFO) { - register thread_sched_info_t sched_info; + thread_sched_info_t sched_info; if (*thread_info_count < THREAD_SCHED_INFO_COUNT) { return KERN_INVALID_ARGUMENT; @@ -1584,7 +1602,7 @@ kern_return_t thread_info( } kern_return_t thread_abort( - register thread_t thread) + thread_t thread) { if (thread == THREAD_NULL || thread == current_thread()) { return KERN_INVALID_ARGUMENT; @@ -1649,9 +1667,13 @@ thread_t kernel_thread( continuation_t start, void * arg) { + kern_return_t kr; thread_t thread; - (void) thread_create(task, &thread); + kr = thread_create(task, &thread); + if (kr != KERN_SUCCESS) + return THREAD_NULL; + /* release "extra" ref that thread_create gave us */ thread_deallocate(thread); thread_start(thread, start); @@ -1675,10 +1697,10 @@ thread_t kernel_thread( * This kernel thread runs forever looking for threads to destroy * (when they request that they be destroyed, of course). */ -void reaper_thread_continue(void) +void __attribute__((noreturn)) reaper_thread_continue(void) { for (;;) { - register thread_t thread; + thread_t thread; spl_t s; s = splsched(); @@ -1793,12 +1815,12 @@ thread_unfreeze( void thread_doassign( - register thread_t thread, - register processor_set_t new_pset, + thread_t thread, + processor_set_t new_pset, boolean_t release_freeze) { - register processor_set_t pset; - register boolean_t old_empty, new_empty; + processor_set_t pset; + boolean_t old_empty, new_empty; boolean_t recompute_pri = FALSE; spl_t s; @@ -1956,6 +1978,9 @@ kern_return_t thread_get_assignment( thread_t thread, processor_set_t *pset) { + if (thread == THREAD_NULL) + return KERN_INVALID_ARGUMENT; + *pset = thread->processor_set; pset_reference(*pset); return KERN_SUCCESS; @@ -2101,8 +2126,8 @@ thread_policy( int data) { #if MACH_FIXPRI - register kern_return_t ret = KERN_SUCCESS; - register int temp; + kern_return_t ret = KERN_SUCCESS; + int temp; spl_t s; #endif /* MACH_FIXPRI */ @@ -2218,7 +2243,6 @@ thread_wire( void thread_collect_scan(void) { -#if 0 register thread_t thread, prev_thread; processor_set_t pset, prev_pset; @@ -2271,7 +2295,6 @@ void thread_collect_scan(void) thread_deallocate(prev_thread); if (prev_pset != PROCESSOR_SET_NULL) pset_deallocate(prev_pset); -#endif /* 0 */ } boolean_t thread_collect_allowed = TRUE; @@ -2305,7 +2328,7 @@ void consider_thread_collect(void) #if MACH_DEBUG vm_size_t stack_usage( - register vm_offset_t stack) + vm_offset_t stack) { int i; @@ -2322,7 +2345,7 @@ vm_size_t stack_usage( */ void stack_init( - register vm_offset_t stack) + vm_offset_t stack) { if (stack_check_usage) { int i; @@ -2338,7 +2361,7 @@ void stack_init( */ void stack_finalize( - register vm_offset_t stack) + vm_offset_t stack) { if (stack_check_usage) { vm_size_t used = stack_usage(stack); @@ -2431,8 +2454,8 @@ kern_return_t processor_set_stack_usage( vm_size_t maxusage; vm_offset_t maxstack; - register thread_t *threads; - register thread_t tmp_thread; + thread_t *threads; + thread_t tmp_thread; unsigned int actual; /* this many things */ unsigned int i; @@ -2550,7 +2573,7 @@ kern_return_t processor_set_stack_usage( void thread_stats(void) { - register thread_t thread; + thread_t thread; int total = 0, rpcreply = 0; queue_iterate(&default_pset.threads, thread, thread_t, pset_threads) { diff --git a/kern/thread.h b/kern/thread.h index 3959dfce..0e85d8c4 100644 --- a/kern/thread.h +++ b/kern/thread.h @@ -70,6 +70,22 @@ struct thread { task_t task; /* Task to which I belong */ queue_chain_t thread_list; /* list of threads in task */ + /* Flags */ + /* The flags are grouped here, but documented at the original + position. */ + union { + struct { + unsigned state:16; + unsigned wake_active:1; + unsigned vm_privilege:1; + unsigned active:1; + }; + event_t event_key; +/* These keys can be used with thread_wakeup and friends. */ +#define TH_EV_WAKE_ACTIVE(t) ((event_t) (&(t)->event_key + 0)) +#define TH_EV_STATE(t) ((event_t) (&(t)->event_key + 1)) + }; + /* Thread bookkeeping */ queue_chain_t pset_threads; /* list of all threads in proc set*/ @@ -92,9 +108,10 @@ struct thread { kern_return_t wait_result; /* outcome of wait - may be examined by this thread WITHOUT locking */ - boolean_t wake_active; /* someone is waiting for this + /* Defined above */ + /* boolean_t wake_active; someone is waiting for this thread to become suspended */ - int state; /* Thread state: */ + /* int state; Thread state: */ /* * Thread states [bits or'ed] */ @@ -129,7 +146,8 @@ struct thread { /* VM global variables */ vm_offset_t recover; /* page fault recovery (copyin/out) */ - boolean_t vm_privilege; /* Can use reserved memory? */ + /* Defined above */ + /* boolean_t vm_privilege; Can use reserved memory? */ /* User-visible scheduling state */ int user_stop_count; /* outstanding stops */ @@ -194,7 +212,8 @@ struct thread { timer_elt_data_t depress_timer; /* timer for priority depression */ /* Ast/Halt data structures */ - boolean_t active; /* how alive is the thread */ + /* Defined above */ + /* boolean_t active; how alive is the thread */ int ast; /* ast's needed. See ast.h */ /* Processor data structures */ @@ -259,6 +278,13 @@ extern kern_return_t thread_create( thread_t *child_thread); extern kern_return_t thread_terminate( thread_t thread); +extern kern_return_t thread_terminate_release( + thread_t thread, + task_t task, + mach_port_t thread_name, + mach_port_t reply_port, + vm_offset_t address, + vm_size_t size); extern kern_return_t thread_suspend( thread_t thread); extern kern_return_t thread_resume( @@ -338,14 +364,12 @@ extern kern_return_t thread_halt( boolean_t must_halt); extern void thread_halt_self(void); extern void thread_force_terminate(thread_t); -extern void thread_set_own_priority( - int priority); extern thread_t kernel_thread( task_t task, void (*start)(void), void * arg); -extern void reaper_thread(void); +extern void reaper_thread(void) __attribute__((noreturn)); #if MACH_HOST extern void thread_freeze( @@ -384,4 +408,9 @@ extern void thread_unfreeze( #define current_space() (current_task()->itk_space) #define current_map() (current_task()->map) +#if MACH_DEBUG +void stack_init(vm_offset_t stack); +void stack_finalize(vm_offset_t stack); +#endif /* MACH_DEBUG */ + #endif /* _KERN_THREAD_H_ */ diff --git a/kern/thread_swap.c b/kern/thread_swap.c index f29bd5b7..20ad0409 100644 --- a/kern/thread_swap.c +++ b/kern/thread_swap.c @@ -86,8 +86,7 @@ void swapper_init(void) * our callers have already tried that route. */ -void thread_swapin(thread) - thread_t thread; +void thread_swapin(thread_t thread) { switch (thread->state & TH_SWAP_STATE) { case TH_SWAPPED: @@ -97,7 +96,7 @@ void thread_swapin(thread) thread->state = (thread->state & ~TH_SWAP_STATE) | TH_SW_COMING_IN; swapper_lock(); - enqueue_tail(&swapin_queue, (queue_entry_t) thread); + enqueue_tail(&swapin_queue, &(thread->links)); swapper_unlock(); thread_wakeup((event_t) &swapin_queue); break; @@ -124,16 +123,18 @@ void thread_swapin(thread) * it on a run queue. No locks should be held on entry, as it is * likely that this routine will sleep (waiting for stack allocation). */ -void thread_doswapin(thread) - register thread_t thread; +kern_return_t thread_doswapin(thread_t thread) { + kern_return_t kr; spl_t s; /* * Allocate the kernel stack. */ - stack_alloc(thread, thread_continue); + kr = stack_alloc(thread, thread_continue); + if (kr != KERN_SUCCESS) + return kr; /* * Place on run queue. @@ -146,6 +147,7 @@ void thread_doswapin(thread) thread_setrun(thread, TRUE); thread_unlock(thread); (void) splx(s); + return KERN_SUCCESS; } /* @@ -154,10 +156,10 @@ void thread_doswapin(thread) * This procedure executes as a kernel thread. Threads that need to * be swapped in are swapped in by this thread. */ -void swapin_thread_continue(void) +void __attribute__((noreturn)) swapin_thread_continue(void) { for (;;) { - register thread_t thread; + thread_t thread; spl_t s; s = splsched(); @@ -165,13 +167,20 @@ void swapin_thread_continue(void) while ((thread = (thread_t) dequeue_head(&swapin_queue)) != THREAD_NULL) { + kern_return_t kr; swapper_unlock(); (void) splx(s); - thread_doswapin(thread); /* may block */ + kr = thread_doswapin(thread); /* may block */ s = splsched(); swapper_lock(); + + if (kr != KERN_SUCCESS) { + enqueue_head(&swapin_queue, + (queue_entry_t) thread); + break; + } } assert_wait((event_t) &swapin_queue, FALSE); diff --git a/kern/thread_swap.h b/kern/thread_swap.h index 31130301..d032accf 100644 --- a/kern/thread_swap.h +++ b/kern/thread_swap.h @@ -37,8 +37,7 @@ */ extern void swapper_init(void); extern void thread_swapin(thread_t thread); -extern void thread_doswapin(thread_t thread); -extern void swapin_thread(void); -extern void thread_swapout(thread_t thread); +extern kern_return_t thread_doswapin(thread_t thread); +extern void swapin_thread(void) __attribute__((noreturn)); #endif /* _KERN_THREAD_SWAP_H_ */ diff --git a/kern/time_stamp.c b/kern/time_stamp.c index 22885b18..ee141a0e 100644 --- a/kern/time_stamp.c +++ b/kern/time_stamp.c @@ -32,31 +32,18 @@ /* * ts.c - kern_timestamp system call. */ -#ifdef multimax -#include <mmax/timer.h> -#endif /* multimax */ - - - kern_return_t -kern_timestamp(tsp) -struct tsval *tsp; +kern_timestamp(struct tsval *tsp) { -#ifdef multimax - struct tsval temp; - temp.low_val = FRcounter; - temp.high_val = 0; -#else /* multimax */ /* temp.low_val = 0; temp.high_val = ts_tick_count; */ time_value_t temp; temp = time; -#endif /* multimax */ - if (copyout((char *)&temp, - (char *)tsp, + if (copyout(&temp, + tsp, sizeof(struct tsval)) != KERN_SUCCESS) return(KERN_INVALID_ADDRESS); return(KERN_SUCCESS); @@ -66,10 +53,7 @@ struct tsval *tsp; * Initialization procedure. */ -void timestamp_init() +void timestamp_init(void) { -#ifdef multimax -#else /* multimax */ ts_tick_count = 0; -#endif /* multimax */ } diff --git a/kern/timer.c b/kern/timer.c index ec0524a8..79ada27e 100644 --- a/kern/timer.c +++ b/kern/timer.c @@ -33,24 +33,22 @@ #include <kern/cpu_number.h> #include <kern/assert.h> -#include <kern/macro_help.h> +#include <kern/macros.h> timer_t current_timer[NCPUS]; timer_data_t kernel_timer[NCPUS]; -void timer_init(); /* forward */ - /* * init_timers initializes all non-thread timers and puts the * service routine on the callout queue. All timers must be * serviced by the callout routine once an hour. */ -void init_timers() +void init_timers(void) { - register int i; - register timer_t this_timer; + int i; + timer_t this_timer; /* * Initialize all the kernel timers and start the one @@ -68,9 +66,7 @@ void init_timers() /* * timer_init initializes a single timer. */ -void timer_init(this_timer) -register -timer_t this_timer; +void timer_init(timer_t this_timer) { this_timer->low_bits = 0; this_timer->high_bits = 0; @@ -94,8 +90,7 @@ timer_t this_timer; * exactly once for each cpu during the boot sequence. */ void -start_timer(timer) -timer_t timer; +start_timer(timer_t timer) { timer->tstamp = get_timestamp(); current_timer[cpu_number()] = timer; @@ -108,8 +103,7 @@ timer_t timer; * from user mode. */ void -time_trap_uentry(ts) -unsigned ts; +time_trap_uentry(unsigned ts) { int elapsed; int mycpu; @@ -150,7 +144,7 @@ unsigned ts; * user mode. */ void -time_trap_uexit(ts) +time_trap_uexit(int ts) { int elapsed; int mycpu; @@ -194,9 +188,9 @@ time_trap_uexit(ts) * saved for time_int_exit. */ timer_t -time_int_entry(ts,new_timer) -unsigned ts; -timer_t new_timer; +time_int_entry( + unsigned ts, + timer_t new_timer) { int elapsed; int mycpu; @@ -235,9 +229,9 @@ timer_t new_timer; * it. */ void -time_int_exit(ts, old_timer) -unsigned ts; -timer_t old_timer; +time_int_exit( + unsigned ts, + timer_t old_timer) { int elapsed; int mycpu; @@ -282,8 +276,7 @@ timer_t old_timer; * Caller must lock out interrupts. */ void -timer_switch(new_timer) -timer_t new_timer; +timer_switch(timer_t new_timer) { int elapsed; int mycpu; @@ -328,9 +321,7 @@ timer_t new_timer; * timer_normalize normalizes the value of a timer. It is * called only rarely, to make sure low_bits never overflows. */ -void timer_normalize(timer) -register -timer_t timer; +void timer_normalize(timer_t timer) { unsigned int high_increment; @@ -356,9 +347,9 @@ timer_t timer; * Keep coherent with db_time_grab below. */ -static void timer_grab(timer, save) -timer_t timer; -timer_save_t save; +static void timer_grab( + timer_t timer, + timer_save_t save) { #if MACH_ASSERT unsigned int passes=0; @@ -390,9 +381,9 @@ timer_save_t save; * above. * */ -void db_timer_grab(timer, save) -timer_t timer; -timer_save_t save; +void db_timer_grab( + timer_t timer, + timer_save_t save) { /* Don't worry about coherency */ @@ -409,10 +400,9 @@ timer_save_t save; */ void -timer_read(timer, tv) -timer_t timer; -register -time_value_t *tv; +timer_read( + timer_t timer, + time_value_t *tv) { timer_save_data_t temp; @@ -436,13 +426,13 @@ time_value_t *tv; * * Needs to be kept coherent with thread_read_times ahead. */ -void thread_read_times(thread, user_time_p, system_time_p) - thread_t thread; - time_value_t *user_time_p; - time_value_t *system_time_p; +void thread_read_times( + thread_t thread, + time_value_t *user_time_p, + time_value_t *system_time_p) { timer_save_data_t temp; - register timer_t timer; + timer_t timer; timer = &thread->user_timer; timer_grab(timer, &temp); @@ -470,13 +460,13 @@ void thread_read_times(thread, user_time_p, system_time_p) * thread_read_times above. * */ -void db_thread_read_times(thread, user_time_p, system_time_p) - thread_t thread; - time_value_t *user_time_p; - time_value_t *system_time_p; +void db_thread_read_times( + thread_t thread, + time_value_t *user_time_p, + time_value_t *system_time_p) { timer_save_data_t temp; - register timer_t timer; + timer_t timer; timer = &thread->user_timer; db_timer_grab(timer, &temp); @@ -505,13 +495,12 @@ void db_thread_read_times(thread, user_time_p, system_time_p) */ unsigned -timer_delta(timer, save) -register -timer_t timer; -timer_save_t save; +timer_delta( + timer_t timer, + timer_save_t save) { timer_save_data_t new_save; - register unsigned result; + unsigned result; timer_grab(timer,&new_save); result = (new_save.high - save->high) * TIMER_HIGH_UNIT + diff --git a/kern/timer.h b/kern/timer.h index 817fa356..2f473cf8 100644 --- a/kern/timer.h +++ b/kern/timer.h @@ -27,7 +27,7 @@ #ifndef _KERN_TIMER_H_ #define _KERN_TIMER_H_ -#include <kern/macro_help.h> +#include <kern/macros.h> #if STAT_TIME /* @@ -168,7 +168,7 @@ extern void time_int_exit(unsigned, timer_t); #define TIMER_DELTA(timer, save, result) \ MACRO_BEGIN \ - register unsigned temp; \ + unsigned temp; \ \ temp = (timer).low_bits; \ if ((save).high != (timer).high_bits_check) { \ @@ -182,4 +182,6 @@ MACRO_END extern void init_timers(void); +void timer_init(timer_t this_timer); + #endif /* _KERN_TIMER_H_ */ @@ -56,12 +56,16 @@ struct xprbuf *xprptr; /* Currently allocated xprbuf */ struct xprbuf *xprlast; /* Pointer to end of circular buffer */ /*VARARGS1*/ -void xpr(msg, arg1, arg2, arg3, arg4, arg5) -char *msg; -int arg1, arg2, arg3, arg4, arg5; +void xpr( + char *msg, + int arg1, + int arg2, + int arg3, + int arg4, + int arg5) { - register spl_t s; - register struct xprbuf *x; + spl_t s; + struct xprbuf *x; /* If we aren't initialized, ignore trace request */ if (!xprenable || (xprptr == 0)) @@ -115,7 +119,7 @@ void xprbootstrap(void) * the previous buffer contents. */ - memset((char *) addr, 0, size); + memset((void *) addr, 0, size); } xprbase = (struct xprbuf *) addr; @@ -132,9 +136,8 @@ void xprinit(void) #if MACH_KDB #include <machine/setjmp.h> +#include <ddb/db_output.h> - -extern void db_printf(); extern jmp_buf_t *db_recover; /* @@ -145,16 +148,16 @@ extern jmp_buf_t *db_recover; * Called with arguments, it can dump xpr buffers in user tasks, * assuming they use the same format as the kernel. */ -void xpr_dump(base, nbufs) - struct xprbuf *base; - int nbufs; +void xpr_dump( + struct xprbuf *base, + int nbufs) { jmp_buf_t db_jmpbuf; jmp_buf_t *prev; struct xprbuf *last, *ptr; - register struct xprbuf *x; + struct xprbuf *x; int i; - spl_t s; + spl_t s = s; if (base == 0) { base = xprbase; @@ -34,7 +34,7 @@ * which will expand into the following code: * if (xprflags & XPR_SYSCALLS) * xpr("syscall: %d, 0x%x\n", syscallno, arg1); - * Xpr will log the pointer to the printf string and up to 6 arguements, + * Xpr will log the pointer to the printf string and up to 6 arguments, * along with a timestamp and cpuinfo (for multi-processor systems), into * a circular buffer. The actual printf processing is delayed until after * the buffer has been collected. It is assumed that the text/data segments |