commit-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnumach] 01/02: Imported Upstream version 1.4+git20150704


From: Samuel Thibault
Subject: [gnumach] 01/02: Imported Upstream version 1.4+git20150704
Date: Sun, 05 Jul 2015 00:42:26 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to branch master
in repository gnumach.

commit f7ae367c3e8292fec0cbc92598d2e75e9ce37371
Author: Samuel Thibault <address@hidden>
Date:   Sat Jul 4 22:34:50 2015 +0000

    Imported Upstream version 1.4+git20150704
---
 ChangeLog                                | 429 ++++++++++++++
 Makefile.am                              |   5 +-
 Makefile.in                              | 196 +++----
 Makefrag.am                              |  15 +-
 Makerules.mig.am                         |  10 +
 NEWS                                     |   6 +-
 config.h.in                              |   3 +
 configfrag.ac                            |   2 +-
 configure                                |  30 +-
 ddb/db_print.c                           |  20 +-
 ddb/db_trap.c                            |   4 +
 device/blkio.c                           |   2 +-
 device/blkio.h                           |   2 +-
 device/cons.h                            |  11 +
 device/dev_master.h                      |   2 +-
 device/ds_routines.c                     | 124 ++---
 device/io_req.h                          |   2 +-
 device/net_io.h                          |   2 +-
 doc/mach.info                            |   2 +-
 doc/mach.info-1                          |   4 +-
 doc/mach.info-2                          |   2 +-
 doc/stamp-vti                            |   4 +-
 doc/version.texi                         |   4 +-
 i386/configfrag.ac                       |   4 +
 i386/grub/misc.h                         |   2 +-
 i386/i386/db_trace.c                     |   2 +-
 i386/i386/pcb.c                          |  12 +-
 i386/i386/phys.c                         |  25 +-
 i386/i386/xen.h                          |   2 +-
 i386/i386at/conf.c                       |   6 +
 i386/i386at/cons_conf.c                  |   7 +
 i386/i386at/immc.c                       |  74 ++-
 i386/i386at/kd.c                         |   2 +-
 i386/i386at/kd.h                         |   1 +
 i386/i386at/model_dep.c                  |   9 +
 i386/i386at/rtc.c                        |   6 +-
 i386/intel/read_fault.c                  |   2 +-
 include/mach_debug/ipc_info.h            |  23 -
 include/mach_debug/mach_debug.defs       |  21 +-
 include/mach_debug/mach_debug_types.defs |   7 +-
 ipc/ipc_entry.c                          | 790 +++-----------------------
 ipc/ipc_entry.h                          |  69 +--
 ipc/ipc_hash.c                           | 620 ---------------------
 ipc/ipc_hash.h                           |  96 ----
 ipc/ipc_init.c                           |   6 +-
 ipc/ipc_kmsg.c                           | 158 ++----
 ipc/ipc_kmsg.h                           |   2 +-
 ipc/ipc_mqueue.h                         |   2 +-
 ipc/ipc_object.c                         |  23 +-
 ipc/ipc_object.h                         |   2 +-
 ipc/ipc_port.c                           |   4 +-
 ipc/ipc_port.h                           |   2 +-
 ipc/ipc_right.c                          |  41 +-
 ipc/ipc_space.c                          | 104 +---
 ipc/ipc_space.h                          | 212 ++++++-
 ipc/ipc_splay.c                          | 920 -------------------------------
 ipc/ipc_splay.h                          | 114 ----
 ipc/ipc_table.c                          |  44 --
 ipc/ipc_table.h                          |  55 +-
 ipc/mach_debug.c                         | 325 -----------
 ipc/mach_msg.c                           | 153 ++---
 ipc/mach_port.c                          |  60 +-
 device/blkio.h => ipc/notify.defs        |  16 +-
 ipc/port.h                               |   5 +-
 kern/assert.h                            |   2 +-
 kern/ast.h                               |   2 +-
 kern/counters.c                          |   3 +
 kern/counters.h                          |   3 +
 kern/exception.c                         |  27 +-
 kern/ipc_mig.c                           |  14 +-
 kern/ipc_tt.c                            |   2 +-
 kern/list.h                              |   4 +-
 kern/macro_help.h                        |  50 --
 kern/macros.h                            |  72 +++
 kern/pc_sample.h                         |   2 +-
 kern/printf.h                            |  13 +-
 kern/processor.c                         |   2 +
 kern/rbtree.h                            |   9 +-
 kern/rdxtree.c                           | 830 ++++++++++++++++++++++++++++
 kern/rdxtree.h                           | 209 +++++++
 kern/rdxtree_i.h                         |  66 +++
 kern/refcount.h                          |   2 +-
 kern/sched.h                             |   2 +-
 kern/sched_prim.c                        |   2 +-
 kern/sched_prim.h                        |   2 +-
 kern/slab.c                              |   2 +-
 kern/startup.c                           |   2 +
 kern/syscall_subr.c                      |   4 +-
 kern/task.c                              |   8 +-
 kern/thread.c                            |  35 +-
 kern/thread_swap.c                       |  17 +-
 kern/thread_swap.h                       |   2 +-
 kern/timer.c                             |   2 +-
 kern/timer.h                             |   2 +-
 linux/Makefrag.am                        |   5 +
 linux/dev/drivers/block/ahci.c           |  47 +-
 linux/dev/include/linux/types.h          |   9 +
 linux/src/include/asm-i386/bitops.h      |   6 +-
 linux/src/include/asm-i386/semaphore.h   |  24 +-
 linux/src/include/linux/compiler-gcc5.h  |  67 +++
 version.m4                               |   2 +-
 vm/vm_fault.c                            |   2 +-
 vm/vm_kern.c                             | 104 +---
 vm/vm_kern.h                             |   2 -
 vm/vm_map.h                              |   2 +-
 vm/vm_object.c                           |  26 +-
 vm/vm_object.h                           |   2 +-
 vm/vm_page.h                             |   2 +-
 108 files changed, 2665 insertions(+), 3936 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2205952..10f18ee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,432 @@
+2015-06-30  Justus Winter  <address@hidden>
+
+       Fix re-configuring out-of-tree builds
+       Previously, running `../configure ...' to reconfigure an out-of-tree
+       build would link `machine' to `i386/i386' instead of `../i386/i386'
+       (i.e. point to the build directory instead to the source) if
+       `i386/i386' also exists in the build directory because of a previous
+       build.
+
+       * configfrag.ac: Prefix machine link target with `$srcdir'.
+
+2015-06-30  Samuel Thibault  <address@hidden>
+
+       Fix restoring interrupts on timeout
+       * linux/dev/drivers/block/ahci.c (ahci_identify): Restore flags before
+       returning on timeout.
+
+2015-06-29  Samuel Thibault  <address@hidden>
+
+       Print about powered-down AHCI ports
+       * linux/dev/drivers/block/ahci.c (ahci_probe_dev): Print messages when
+       device is present but powered down.
+
+2015-06-28  Justus Winter  <address@hidden>
+
+       ddb: automatically display stack traces
+       * ddb/db_trap.c (db_task_trap): Automatically display stack traces if
+       an unexpected trap occurs.
+
+2015-06-28  Justus Winter  <address@hidden>
+
+       i386: improve the immediate console
+       Improve the immediate console to the point that it can be enabled and
+       display e.g. assertion failures from very early on (i.e. from
+       `c_boot_entry').
+
+       * device/cons.h (romgetc, romputc): New declarations.
+       * i386/configfrag.ac: Add configuration variable.
+       * i386/i386at/conf.c (dev_name_list): Add entry.
+       * i386/i386at/cons_conf.c (constab): Add entry.
+       * i386/i386at/immc.c: Add missing includes.
+       (immc_cnprobe, immc_cninit, immc_cngetc, immc_romputc): New functions.
+       (immc_cnputc): Fix signature, use virtual addresses.
+       * i386/i386at/immc.h: New file.
+       * i386/i386at/kd.c: Use `#if ENABLE_IMMEDIATE_CONSOLE'.
+       * i386/i386at/kd.h (kd_setpos): Add missing declaration.
+       * i386/i386at/model_dep.c (c_boot_entry): Install immediate console as
+       early boot console.
+
+2015-06-26  Justus Winter  <address@hidden>
+
+       i386: add comment
+       * i386/i386at/model_dep.c (rebootflag): Explain flag.
+
+2015-06-20  Justus Winter  <address@hidden>
+
+       kern: fix error handling
+       This avoids calling `thread_deallocate' with an uninitialized value,
+       as found by the Clang Static Analyzer.
+
+       * kern/thread.c (kernel_thread): Fix error handling.
+
+2015-06-09  Justus Winter  <address@hidden>
+
+       kern: add function attributes to the printf-functions
+       * kern/printf.h (sprintf, snprintf, vsnprintf, printf): Add the
+       `printf' function attribute that allows the compiler to check the
+       format strings and arguments.
+
+2015-06-05  Flávio Cruz  <address@hidden>
+
+       Fix typo
+       * vm/vm_kern.c (kmem_alloc_aligned): Fix typo.
+
+       Use custom port macros.
+       * ipc/ipc_port.c (ipc_port_alloc_special): Use ip_alloc and ip_lock_init
+       macros instead of manually inlining them.
+
+2015-05-31  Justus Winter  <address@hidden>
+
+       ipc: fix typo
+       * ipc/notify.defs: Fix typo.
+
+       Include the notify protocol in `gnumach.msgids'
+       * Makefrag.am (gnumach.msgids): Add `notify.msgids' as prerequisite.
+       * Makerules.mig.am: Add rule to generate the list of message ids when
+       neither the client nor the server stubs are required.
+       * ipc/notify.defs: New file.
+
+2015-05-29  Justus Winter  <address@hidden>
+
+       kern: fix argument handling
+       Previously, the processor argument was not checked.  If called with a
+       non-processor argument (like a task), `processor' is set to NULL,
+       triggering a page fault.  Likewise for the other functions.
+
+       * kern/processor.c (processor_get_assignment): Fix argument handling.
+       * kern/task.c (task_get_assignment): Likewise.
+       * kern/thread.c (thread_get_assignment): Likewise.
+
+2015-05-23  Justus Winter  <address@hidden>
+
+       Restrict `-fno-strict-aliasing' to the Linux drivers
+       * Makefile.am: Move `-fno-strict-aliasing'...
+       * linux/Makefrag.am: ... here.
+
+       i386: avoid breaking the strict-aliasing rules
+       * i386/i386/pcb.c (switch_ktss): Cleanly convert the value.
+
+       kern: avoid breaking the strict-aliasing rules
+       * kern/exception.c (exception_parse_reply): Use `BAD_TYPECHECK'.
+
+       vm: drop unused `kmem_realloc'
+       * vm/vm_kern.c (kmem_realloc): Remove function.
+       (kmem_alloc_wired): Adopt comment.
+       * vm/vm_kern.h (kmem_realloc): Remove declaration.
+
+2015-05-23  Samuel Thibault  <address@hidden>
+
+       Add stdint integer types in Linux glue
+       * linux/dev/include/linux/types.h (int8_t, uint8_t, int16_t, uint16_t,
+       int32_t, uint32_t, int64_t, uint64_t): New types.
+
+2015-05-22  Justus Winter  <address@hidden>
+
+       ipc: drop remnants of the IPC tables
+       * ipc/ipc_table.c (ipc_table_entries): Remove.
+       (ipc_table_entries_size): Likewise.
+       (ipc_table_init): Remove initialization of `ipc_table_entries'.
+       (ipc_table_realloc): Remove function.
+       * ipc/ipc_table.h: Adjust comments.
+       (ipc_table_entries): Remove declaration.
+       (ipc_table_realloc): Likewise.
+       (it_entries_{alloc,reallocable,realloc,free}): Remove macros.
+
+       ipc: drop size parameter from `ipc_space_create'
+       * ipc/ipc_space.c (ipc_space_create): Drop size parameter.
+       * ipc/ipc_space.h (ipc_space_create): Adopt declaration, fix comment.
+       * kern/ipc_tt.c (ipc_task_init): Adopt accordingly.
+
+2015-05-20  Justus Winter  <address@hidden>
+
+       ipc: inline key ipc entry lookup functions
+       Declare functions looking up IPC entries that were previously inlined
+       manually with `static inline' so that they will be inlined into the
+       fast paths by the compiler.
+
+       * ipc/ipc_entry.c (ipc_entry_lookup, ipc_entry_get,
+       ipc_entry_dealloc): Move functions...
+       * ipc/ipc_space.h: ... here, and declare them as `static inline'.
+       * ipc/ipc_entry.h: Drop associated declarations.
+
+2015-05-20  Justus Winter  <address@hidden>
+
+       ipc: replace the IPC table with a radix tree
+       Currently, the port names are mapped to an IPC object (e.g. a port)
+       using a table.  This, however, requires large chunks of continuous
+       memory, and leads to scalability problems as virtual kernel memory is
+       a scarce resource.  To avoid excessive overhead, non-contiguous port
+       names are spilled into a splay tree.
+
+       Replace the IPC table with a radix tree.  As the radix tree is able to
+       store non-contiguous names with reasonable overhead, we can drop the
+       splay tree as well.
+
+       * ipc/ipc_entry.c (ipc_entry_tree_collision): Remove function.
+       (ipc_entry_cache): New variable.
+       (ipc_entry_lookup): Replace with a radix tree lookup.
+       (ipc_entry_get): The free list handling is changed a little.  Adopt
+       accordingly.
+       (ipc_entry_free_name): New function.
+       (ipc_entry_alloc): Adopt accordingly.
+       (ipc_entry_alloc_name): Likewise.
+       (ipc_entry_dealloc): Likewise.
+       (ipc_entry_grow_table): Remove function.
+       * ipc/ipc_entry.h (struct ipc_entry): Update comment, add field for
+       name and free list, remove unused fields.
+       (ipc_entry_cache, ie_alloc, ie_free): New declarations.
+       (struct ipc_tree_entry): Remove.  Also remove any related declarations.
+       (ipc_entry_grow_table): Remove declaration.
+       * ipc/ipc_init.c (ipc_bootstrap): Adopt initialization.
+       * ipc/ipc_kmsg.c (ipc_kmsg_copyout_header): Use `ipc_entry_alloc'
+       instead of re-coding it.  Adopt free list handling.
+       (ipc_kmsg_copyout_object): Adopt free list handling, store the name.
+       * ipc/ipc_object.c (ipc_object_copyout): Likewise.
+       (ipc_object_copyout_multiname): Likewise.
+       * ipc/ipc_space.c (ipc_space_create): Initialize radix tree and free 
list.
+       Drop table and splay tree initialization.
+       (ipc_space_destroy): Free ipc entries and radix tree, remove table and
+       splay tree cleanup.
+       * ipc/ipc_space.h (struct ipc_space): Add radix tree, free list, and 
size.
+       Remove all fields related to the table and splay tree.
+       * ddb/db_print.c (db_port_iterate): Adopt iteration.
+       (db_lookup_port): Adopt lookup.
+       * include/mach_debug/ipc_info.h: Remove unused parts of the debug 
interface.
+       * include/mach_debug/mach_debug.defs: Likewise.
+       * include/mach_debug/mach_debug_types.defs: Likewise.
+       * ipc/mach_debug.c: Likewise.
+       * ipc/ipc_right.c (ipc_right_reverse): Adopt lookup, store name.
+       (ipc_right_check): Adopt removal.
+       (ipc_right_destroy): Likewise.
+       (ipc_right_dealloc): Likewise.
+       (ipc_right_delta): Likewise.
+       (ipc_right_copyin): Adopt insertion, adopt removal.
+       (ipc_right_copyin_two): Adopt removal.
+       (ipc_right_copyout): Adopt insertion, adopt removal.
+       (ipc_right_rename): Likewise, also update comment.
+       * ipc/mach_port.c (mach_port_names): Adopt iteration.
+       (mach_port_get_set_status): Likewise.
+       * ipc/port.h: Update comment.
+       * ipc/ipc_hash.c: Delete file.
+       * ipc/ipc_hash.h: Likewise.
+       * ipc/ipc_splay.c: Likewise.
+       * ipc/ipc_splay.h: Likewise.
+       * Makefrag.am (libkernel_a_SOURCES): Remove these files.
+
+2015-05-20  Justus Winter  <address@hidden>
+
+       ipc: replace reverse hash table with a radix tree
+       Currently, there is a hash table mapping (space, object) tuples to
+       `ipc_entry' objects.  This hash table is intertwined with the IPC
+       tables.  There is one hash table per IPC space, but it is only for the
+       entries in the IPC table.  This hash table is called `local' in the
+       source.  All IPC entries being spilled into the splay tree are instead
+       mapped by a global hash table.
+
+       Replace the local (i.e. per IPC space) reverse hash table with a radix
+       tree.
+
+       * ipc/ipc_entry.c (ipc_entry_grow_table): Adjust accordingly.
+       * ipc/ipc_entry.h (struct ipc_entry): Adjust comment.
+       * ipc/ipc_hash.c: Adjust comment explaining the local lookup table.
+       (IPC_LOCAL_HASH_INVARIANT): New macro.
+       (ipc_hash_local_lookup): Use the new `ipc_reverse_lookup' function.
+       (ipc_hash_local_insert): Use the new `ipc_reverse_insert' function.
+       (ipc_hash_local_delete): Use the new `ipc_reverse_remove' function.
+       * ipc/ipc_space.c (ipc_space_create): Initialize radix tree.
+       (ipc_space_destroy): Free radix tree.
+       * ipc/ipc_space.h (struct ipc_space): Add radix tree.
+       (ipc_reverse_insert): New function.
+       (ipc_reverse_remove): Likewise.
+       (ipc_reverse_remove_all): Likewise.
+       (ipc_reverse_lookup): Likewise.
+       * ipc/ipc_right.c (ipc_right_clean): Update comment.
+
+2015-05-20  Justus Winter  <address@hidden>
+
+       ipc: undo manual inlining of `ipc_entry_X' functions
+       Today we can rely on the compiler to inline functions.  Undoing this
+       manual optimization is a first step to replace the IPC tables.
+
+       * ipc/mach_msg.c (mach_msg_trap): Undo the manual inlining of
+       `ipc_entry_lookup', `ipc_entry_dealloc', and `ipc_entry_get'.
+       * ipc/ipc_kmsg.c (ipc_kmsg_copyin_header, ipc_kmsg_copyout_header): 
Likewise.
+       * kern/exception.c (exception_raise): Likewise.
+       * kern/ipc_mig.c (fast_send_right_lookup): Likewise.
+
+2015-05-20  Justus Winter  <address@hidden>
+
+       kern: add radix tree library
+       Import a radix tree library from Richard Braun's librbraun.
+
+       * Makefile.am (clib_routines): Steal `__ffsdi2'.
+       * Makefrag.am (libkernel_a_SOURCES): Add new files.
+       * kern/rdxtree.c: New file.
+       * kern/rdxtree.h: Likewise.
+       * kern/rdxtree_i.h: Likewise.
+       * kern/startup.c (setup_main): Initialize radix tree library.
+
+2015-05-20  Justus Winter  <address@hidden>
+
+       kern: gracefully handle resource shortage
+       * kern/thread.c (stack_alloc): Report resource shortage.
+       * kern/sched_prim.h (stack_alloc): Adjust declaration accordingly.
+       * kern/thread_swap.c (thread_doswapin): Report resource shortage.
+       (swapin_thread_continue): If the swap-in fails, put the thread back on
+       the queue and go back to sleep.
+       * kern/thread_swap.h (thread_doswapin): Adjust declaration accordingly.
+
+       vm: gracefully handle resource shortage
+       * vm/vm_object.c (vm_object_copy_call): Gracefully handle resource
+       shortage by doing the allocation earlier and aborting the function if
+       unsuccessful.
+
+       kern: gracefully handle resource shortage
+       * kern/task.c (task_create): Gracefully handle resource shortage.
+
+2015-05-19  Justus Winter  <address@hidden>
+
+       kern: import `macros.h' from x15
+       Import the macro definitions from the x15 kernel project, and replace
+       all similar definitions littered all over the place with it.
+
+       Importing this file will make importing code from the x15 kernel
+       easier.  We are already using the red-black tree implementation and
+       the slab allocator from it, and we will import even more code in the
+       near future.
+
+       * kern/list.h: Do not define `structof', include `macros.h' instead.
+       * kern/rbtree.h: Likewise.
+       * kern/slab.c: Do not define `ARRAY_SIZE', include `macros.h' instead.
+       * i386/grub/misc.h: Likewise.
+       * i386/i386/xen.h: Do not define `barrier', include `macros.h' instead.
+       * kern/macro_help.h: Delete file.  Replaced by `macros.h'.
+       * kern/macros.h: New file.
+       * Makefrag.am (libkernel_a_SOURCES): Add new file, remove old file.
+       * device/dev_master.h: Adopt accordingly.
+       * device/io_req.h: Likewise.
+       * device/net_io.h: Likewise.
+       * i386/intel/read_fault.c: Likewise.
+       * ipc/ipc_kmsg.h: Likewise.
+       * ipc/ipc_mqueue.h: Likewise.
+       * ipc/ipc_object.h: Likewise.
+       * ipc/ipc_port.h: Likewise.
+       * ipc/ipc_space.h: Likewise.
+       * ipc/ipc_splay.c: Likewise.
+       * ipc/ipc_splay.h: Likewise.
+       * kern/assert.h: Likewise.
+       * kern/ast.h: Likewise.
+       * kern/pc_sample.h: Likewise.
+       * kern/refcount.h: Likewise.
+       * kern/sched.h: Likewise.
+       * kern/sched_prim.c: Likewise.
+       * kern/timer.c: Likewise.
+       * kern/timer.h: Likewise.
+       * vm/vm_fault.c: Likewise.
+       * vm/vm_map.h: Likewise.
+       * vm/vm_object.h: Likewise.
+       * vm/vm_page.h: Likewise.
+
+2015-05-17  Justus Winter  <address@hidden>
+
+       i386: avoid compiler warning
+       * i386/i386/phys.c (pmap_zero_page, pmap_copy_page, copy_to_phys,
+       copy_from_phys): Avoid compiler warning about `map' being used
+       uninitialized.
+
+2015-05-14  Justus Winter  <address@hidden>
+
+       i386: use macro to compute address of saved registers
+       * i386/i386/pcb.c (stack_attach): Use `USER_REGS'.
+       (stack_handoff): Likewise.
+
+2015-05-02  Samuel Thibault  <address@hidden>
+
+       Fix semaphore failure path special calling convention
+       * linux/src/include/asm-i386/semaphore.h (down): Pass semaphore address 
to
+       down_failed through ecx.
+       (down_interruptible): Likewise to down_failed_interruptible.
+       (up): Likewise to up_wakeup.
+
+2015-05-02  Justus Winter  <address@hidden>
+
+       kern: fix comment
+       * kern/rbtree.h: Fix comment.
+
+2015-05-02  Samuel Thibault  <address@hidden>
+
+       Fix warning
+       * i386/i386at/rtc.c (rtcget, rtcput): Make functions take an rtc_st
+       structure which it casts to char * itself.
+
+       Fix warnings
+       * device/ds_routines.c (device_open, ds_open_done, device_close,
+       device_write, device_write_inband, ds_write_done, device_read,
+       device_read_inband, ds_read_done, device_set_status, 
mach_device_get_status,
+       device_set_filter, device_map, ds_no_senders): Convert from K&R 
declaration,
+       fix type of `device' into void*.
+
+       Fix block_io_mmap prototype
+       * device/blkio.c (block_io_mmap): Fix prototype of dummy function.
+       * device/blkio.h (block_io_mmap): Likewise.
+
+2015-05-01  Samuel Thibault  <address@hidden>
+
+       Use gnu89 inline style
+       * Makefile.am (AM_CFLAGS): Add -fgnu89-inline option.
+
+2015-05-01  Samuel Thibault  <address@hidden>
+
+       Replace clobbers with earlyclobbers
+       Newer gccs consider the former "impossible"
+
+       * linux/src/include/asm-i386/bitops.h (find_first_zero_bit): Replace
+       clobbers with earlyclobbers.
+       * linux/src/include/asm-i386/semaphore.h (down, down_interruptible, up):
+       Likewise.
+
+2015-04-30  Samuel Thibault  <address@hidden>
+
+       Fix build with gcc-5
+       * linux/src/include/linux/compiler-gcc5.h: New file.
+
+2015-04-24  Justus Winter  <address@hidden>
+
+       kern: avoid hardcoding the lowest priority
+       The number of priorities has been changed from 32 to 50 in
+       6a234201081156e6d5742e7eeabb68418b518fad.
+
+       * kern/syscall_subr.c (thread_depress_priority): Avoid hardcoding the
+       lowest priority.
+
+2015-04-23  Justus Winter  <address@hidden>
+
+       kern: disable stack allocation counters by default
+       Disable the stack allocation counters by default.  Casual checking
+       revealed that the hits-to-miss ratio is excellent.
+
+       * kern/thread.c (stack_alloc_{hits,misses,max}): Move variables...
+       * kern/counters.c: ... here, and add the usual counter prefix.
+       * kern/counters.h: New declarations.
+
+2015-04-23  Samuel Thibault  <address@hidden>
+
+       Avoid accessing ip_protected_payload without the lock.
+       * ipc/ipc_kmsg.c (ipc_kmsg_copyout_header): Avoid accessing
+       dest->ip_protected_payload without the lock.
+       * ipc/mach_msg.c (ipc/mach_msg.c): Avoid accessing
+       dest_port->ip_protected_payload without the lock.
+
+       Prepend 0x to hexadecimal offset
+       * i386/i386/db_trace.c (db_i386_stack_trace): Prepend 0x to hexadecimal 
offset.
+
+2015-04-10  Thomas Schwinge  <address@hidden>
+
+       GNU Mach 1.5.
+       * version.m4 (AC_PACKAGE_VERSION): Set to 1.5.
+       * NEWS: Finalize for 1.5.
+
 2015-03-19  Samuel Thibault  <address@hidden>
 
        Give the Debian package name for the non-multilib libc.a
diff --git a/Makefile.am b/Makefile.am
index 2c39451..913db55 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -59,9 +59,9 @@ AM_CFLAGS += \
 AM_CFLAGS += \
        -Wall
 
-# See <http://lists.gnu.org/archive/html/bug-hurd/2006-01/msg00148.html>.
+# We need the GNU-style inline
 AM_CFLAGS += \
-       -fno-strict-aliasing
+       -fgnu89-inline
 
 # The smashing stack protector might be enabled by default, but might emit
 # unsuitable code.
@@ -161,6 +161,7 @@ clib_routines := memcmp memcpy memmove                      
        \
                 htonl htons ntohl ntohs                        \
                 udivdi3 __udivdi3                              \
                 __rel_iplt_start __rel_iplt_end                \
+                __ffsdi2                                       \
                 _START _start etext _edata end _end # actually ld magic, not 
libc.
 gnumach-undef: gnumach.$(OBJEXT)
        $(NM_V) $(NM) -u $< | sed 's/  *U  *//' | sort -u > $@
diff --git a/Makefile.in b/Makefile.in
index 70f2758..df09b69 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1234,20 +1234,19 @@ am__libkernel_a_SOURCES_DIST = ddb/db_access.c 
ddb/db_access.h \
        ddb/db_trap.c ddb/db_trap.h ddb/db_variables.c \
        ddb/db_variables.h ddb/db_watch.c ddb/db_watch.h \
        ddb/db_write_cmd.c ddb/db_write_cmd.h ddb/nlist.h ddb/stab.h \
-       ddb/tr.h ipc/ipc_entry.c ipc/ipc_entry.h ipc/ipc_hash.c \
-       ipc/ipc_hash.h ipc/ipc_init.c ipc/ipc_init.h ipc/ipc_kmsg.c \
-       ipc/ipc_kmsg.h ipc/ipc_kmsg_queue.h ipc/ipc_machdep.h \
-       ipc/ipc_marequest.c ipc/ipc_marequest.h ipc/ipc_mqueue.c \
-       ipc/ipc_mqueue.h ipc/ipc_notify.c ipc/ipc_notify.h \
-       ipc/ipc_object.c ipc/ipc_object.h ipc/ipc_port.c \
-       ipc/ipc_port.h ipc/ipc_print.h ipc/ipc_pset.c ipc/ipc_pset.h \
-       ipc/ipc_right.c ipc/ipc_right.h ipc/ipc_space.c \
-       ipc/ipc_space.h ipc/ipc_splay.c ipc/ipc_splay.h \
-       ipc/ipc_table.c ipc/ipc_table.h ipc/ipc_target.c \
-       ipc/ipc_target.h ipc/ipc_thread.c ipc/ipc_thread.h \
-       ipc/ipc_types.h ipc/mach_msg.c ipc/mach_msg.h ipc/mach_port.c \
-       ipc/mach_port.h ipc/mach_rpc.c ipc/mach_debug.c ipc/port.h \
-       kern/act.c kern/act.h kern/assert.h kern/ast.c kern/ast.h \
+       ddb/tr.h ipc/ipc_entry.c ipc/ipc_entry.h ipc/ipc_init.c \
+       ipc/ipc_init.h ipc/ipc_kmsg.c ipc/ipc_kmsg.h \
+       ipc/ipc_kmsg_queue.h ipc/ipc_machdep.h ipc/ipc_marequest.c \
+       ipc/ipc_marequest.h ipc/ipc_mqueue.c ipc/ipc_mqueue.h \
+       ipc/ipc_notify.c ipc/ipc_notify.h ipc/ipc_object.c \
+       ipc/ipc_object.h ipc/ipc_port.c ipc/ipc_port.h ipc/ipc_print.h \
+       ipc/ipc_pset.c ipc/ipc_pset.h ipc/ipc_right.c ipc/ipc_right.h \
+       ipc/ipc_space.c ipc/ipc_space.h ipc/ipc_table.c \
+       ipc/ipc_table.h ipc/ipc_target.c ipc/ipc_target.h \
+       ipc/ipc_thread.c ipc/ipc_thread.h ipc/ipc_types.h \
+       ipc/mach_msg.c ipc/mach_msg.h ipc/mach_port.c ipc/mach_port.h \
+       ipc/mach_rpc.c ipc/mach_debug.c ipc/port.h kern/act.c \
+       kern/act.h kern/assert.h kern/ast.c kern/ast.h \
        kern/boot_script.h kern/bootstrap.c kern/bootstrap.h \
        kern/counters.c kern/counters.h kern/cpu_number.h kern/debug.c \
        kern/debug.h kern/eventcount.c kern/eventcount.h \
@@ -1258,22 +1257,22 @@ am__libkernel_a_SOURCES_DIST = ddb/db_access.c 
ddb/db_access.h \
        kern/kalloc.h kern/kern_types.h kern/list.h kern/lock.c \
        kern/lock.h kern/lock_mon.c kern/mach_clock.c \
        kern/mach_clock.h kern/mach_factor.c kern/mach_factor.h \
-       kern/machine.c kern/machine.h kern/macro_help.h \
-       kern/pc_sample.c kern/pc_sample.h kern/printf.c kern/printf.h \
-       kern/priority.c kern/priority.h kern/processor.c \
-       kern/processor.h kern/profile.c kern/queue.c kern/queue.h \
-       kern/rbtree.c kern/rbtree.h kern/rbtree_i.h kern/refcount.h \
-       kern/slab.c kern/slab.h kern/sched.h kern/sched_prim.c \
-       kern/sched_prim.h kern/shuttle.h kern/startup.c kern/startup.h \
-       kern/strings.c kern/syscall_emulation.c \
-       kern/syscall_emulation.h kern/syscall_subr.c \
-       kern/syscall_subr.h kern/syscall_sw.c kern/syscall_sw.h \
-       kern/task.c kern/task.h kern/thread.c kern/thread.h \
-       kern/thread_swap.c kern/thread_swap.h kern/time_stamp.c \
-       kern/time_stamp.h kern/timer.c kern/timer.h kern/xpr.c \
-       kern/xpr.h kern/elf-load.c kern/boot_script.c util/putchar.c \
-       util/putchar.h util/puts.c util/atoi.c util/atoi.h \
-       vm/memory_object_proxy.c vm/memory_object_proxy.h \
+       kern/machine.c kern/machine.h kern/macros.h kern/pc_sample.c \
+       kern/pc_sample.h kern/printf.c kern/printf.h kern/priority.c \
+       kern/priority.h kern/processor.c kern/processor.h \
+       kern/profile.c kern/queue.c kern/queue.h kern/rbtree.c \
+       kern/rbtree.h kern/rbtree_i.h kern/rdxtree.c kern/rdxtree.h \
+       kern/rdxtree_i.h kern/refcount.h kern/slab.c kern/slab.h \
+       kern/sched.h kern/sched_prim.c kern/sched_prim.h \
+       kern/shuttle.h kern/startup.c kern/startup.h kern/strings.c \
+       kern/syscall_emulation.c kern/syscall_emulation.h \
+       kern/syscall_subr.c kern/syscall_subr.h kern/syscall_sw.c \
+       kern/syscall_sw.h kern/task.c kern/task.h kern/thread.c \
+       kern/thread.h kern/thread_swap.c kern/thread_swap.h \
+       kern/time_stamp.c kern/time_stamp.h kern/timer.c kern/timer.h \
+       kern/xpr.c kern/xpr.h kern/elf-load.c kern/boot_script.c \
+       util/putchar.c util/putchar.h util/puts.c util/atoi.c \
+       util/atoi.h vm/memory_object_proxy.c vm/memory_object_proxy.h \
        vm/memory_object.c vm/memory_object.h vm/pmap.h vm/vm_debug.c \
        vm/vm_external.c vm/vm_external.h vm/vm_fault.c vm/vm_fault.h \
        vm/vm_init.c vm/vm_init.h vm/vm_kern.c vm/vm_kern.h \
@@ -1450,12 +1449,11 @@ am__libkernel_a_SOURCES_DIST = ddb/db_access.c 
ddb/db_access.h \
 @HOST_ix86_TRUE@@PLATFORM_xen_TRUE@    i386/xen/xen_locore.$(OBJEXT) \
 @HOST_ix86_TRUE@@PLATFORM_xen_TRUE@    i386/xen/xen_boothdr.$(OBJEXT)
 am_libkernel_a_OBJECTS = $(am__objects_2) ipc/ipc_entry.$(OBJEXT) \
-       ipc/ipc_hash.$(OBJEXT) ipc/ipc_init.$(OBJEXT) \
-       ipc/ipc_kmsg.$(OBJEXT) ipc/ipc_marequest.$(OBJEXT) \
-       ipc/ipc_mqueue.$(OBJEXT) ipc/ipc_notify.$(OBJEXT) \
-       ipc/ipc_object.$(OBJEXT) ipc/ipc_port.$(OBJEXT) \
-       ipc/ipc_pset.$(OBJEXT) ipc/ipc_right.$(OBJEXT) \
-       ipc/ipc_space.$(OBJEXT) ipc/ipc_splay.$(OBJEXT) \
+       ipc/ipc_init.$(OBJEXT) ipc/ipc_kmsg.$(OBJEXT) \
+       ipc/ipc_marequest.$(OBJEXT) ipc/ipc_mqueue.$(OBJEXT) \
+       ipc/ipc_notify.$(OBJEXT) ipc/ipc_object.$(OBJEXT) \
+       ipc/ipc_port.$(OBJEXT) ipc/ipc_pset.$(OBJEXT) \
+       ipc/ipc_right.$(OBJEXT) ipc/ipc_space.$(OBJEXT) \
        ipc/ipc_table.$(OBJEXT) ipc/ipc_target.$(OBJEXT) \
        ipc/ipc_thread.$(OBJEXT) ipc/mach_msg.$(OBJEXT) \
        ipc/mach_port.$(OBJEXT) ipc/mach_rpc.$(OBJEXT) \
@@ -1471,15 +1469,16 @@ am_libkernel_a_OBJECTS = $(am__objects_2) 
ipc/ipc_entry.$(OBJEXT) \
        kern/pc_sample.$(OBJEXT) kern/printf.$(OBJEXT) \
        kern/priority.$(OBJEXT) kern/processor.$(OBJEXT) \
        kern/profile.$(OBJEXT) kern/queue.$(OBJEXT) \
-       kern/rbtree.$(OBJEXT) kern/slab.$(OBJEXT) \
-       kern/sched_prim.$(OBJEXT) kern/startup.$(OBJEXT) \
-       kern/strings.$(OBJEXT) kern/syscall_emulation.$(OBJEXT) \
-       kern/syscall_subr.$(OBJEXT) kern/syscall_sw.$(OBJEXT) \
-       kern/task.$(OBJEXT) kern/thread.$(OBJEXT) \
-       kern/thread_swap.$(OBJEXT) kern/time_stamp.$(OBJEXT) \
-       kern/timer.$(OBJEXT) kern/xpr.$(OBJEXT) \
-       kern/elf-load.$(OBJEXT) kern/boot_script.$(OBJEXT) \
-       util/putchar.$(OBJEXT) util/puts.$(OBJEXT) util/atoi.$(OBJEXT) \
+       kern/rbtree.$(OBJEXT) kern/rdxtree.$(OBJEXT) \
+       kern/slab.$(OBJEXT) kern/sched_prim.$(OBJEXT) \
+       kern/startup.$(OBJEXT) kern/strings.$(OBJEXT) \
+       kern/syscall_emulation.$(OBJEXT) kern/syscall_subr.$(OBJEXT) \
+       kern/syscall_sw.$(OBJEXT) kern/task.$(OBJEXT) \
+       kern/thread.$(OBJEXT) kern/thread_swap.$(OBJEXT) \
+       kern/time_stamp.$(OBJEXT) kern/timer.$(OBJEXT) \
+       kern/xpr.$(OBJEXT) kern/elf-load.$(OBJEXT) \
+       kern/boot_script.$(OBJEXT) util/putchar.$(OBJEXT) \
+       util/puts.$(OBJEXT) util/atoi.$(OBJEXT) \
        vm/memory_object_proxy.$(OBJEXT) vm/memory_object.$(OBJEXT) \
        vm/vm_debug.$(OBJEXT) vm/vm_external.$(OBJEXT) \
        vm/vm_fault.$(OBJEXT) vm/vm_init.$(OBJEXT) \
@@ -2438,14 +2437,14 @@ DIST_SUBDIRS =
 #
 # Building a distribution.
 #
-EXTRA_DIST = gensym.awk ipc/mach_port.srv kern/mach.srv kern/mach4.srv \
-       kern/gnumach.srv kern/mach_debug.srv kern/mach_host.srv \
-       kern/task_notify.cli vm/memory_object_default.cli \
-       vm/memory_object_user.cli device/device.srv \
-       device/device_pager.srv device/device_reply.cli \
-       device/memory_object_reply.cli include $(am__append_13) \
-       $(am__append_20) $(am__append_24) $(am__append_26) \
-       $(am__append_30) $(am__append_41) \
+EXTRA_DIST = gensym.awk ipc/mach_port.srv ipc/notify.defs \
+       kern/mach.srv kern/mach4.srv kern/gnumach.srv \
+       kern/mach_debug.srv kern/mach_host.srv kern/task_notify.cli \
+       vm/memory_object_default.cli vm/memory_object_user.cli \
+       device/device.srv device/device_pager.srv \
+       device/device_reply.cli device/memory_object_reply.cli include \
+       $(am__append_13) $(am__append_20) $(am__append_24) \
+       $(am__append_26) $(am__append_30) $(am__append_41) \
        linux/src/drivers/scsi/NCR5380.c \
        linux/src/drivers/scsi/NCR5380.h linux/src/drivers/net/8390.h \
        linux/src/drivers/net/kern_compat.h linux/pcmcia-cs/glue/ds.c \
@@ -2494,9 +2493,9 @@ AM_CCASFLAGS =
 # Yes, this makes the eyes hurt.  But perhaps someone will finally take care of
 # all that scruffy Mach code...  Also see <http://savannah.gnu.org/task/?5726>.
 
-# See <http://lists.gnu.org/archive/html/bug-hurd/2006-01/msg00148.html>.
-AM_CFLAGS = -fno-builtin-log -Wall -fno-strict-aliasing \
-       $(am__append_1) $(am__append_3) $(am__append_124)
+# We need the GNU-style inline
+AM_CFLAGS = -fno-builtin-log -Wall -fgnu89-inline $(am__append_1) \
+       $(am__append_3) $(am__append_124)
 AM_LDFLAGS = 
 
 #
@@ -2546,19 +2545,18 @@ MIGCOM = $(MIG) -n -cc cat - /dev/null
 # particular drivers want the routines.
 # TODO.  Functions in device/subrs.c should each be moved elsewhere.
 libkernel_a_SOURCES = $(am__append_2) ipc/ipc_entry.c ipc/ipc_entry.h \
-       ipc/ipc_hash.c ipc/ipc_hash.h ipc/ipc_init.c ipc/ipc_init.h \
-       ipc/ipc_kmsg.c ipc/ipc_kmsg.h ipc/ipc_kmsg_queue.h \
-       ipc/ipc_machdep.h ipc/ipc_marequest.c ipc/ipc_marequest.h \
-       ipc/ipc_mqueue.c ipc/ipc_mqueue.h ipc/ipc_notify.c \
-       ipc/ipc_notify.h ipc/ipc_object.c ipc/ipc_object.h \
-       ipc/ipc_port.c ipc/ipc_port.h ipc/ipc_print.h ipc/ipc_pset.c \
-       ipc/ipc_pset.h ipc/ipc_right.c ipc/ipc_right.h ipc/ipc_space.c \
-       ipc/ipc_space.h ipc/ipc_splay.c ipc/ipc_splay.h \
-       ipc/ipc_table.c ipc/ipc_table.h ipc/ipc_target.c \
-       ipc/ipc_target.h ipc/ipc_thread.c ipc/ipc_thread.h \
-       ipc/ipc_types.h ipc/mach_msg.c ipc/mach_msg.h ipc/mach_port.c \
-       ipc/mach_port.h ipc/mach_rpc.c ipc/mach_debug.c ipc/port.h \
-       kern/act.c kern/act.h kern/assert.h kern/ast.c kern/ast.h \
+       ipc/ipc_init.c ipc/ipc_init.h ipc/ipc_kmsg.c ipc/ipc_kmsg.h \
+       ipc/ipc_kmsg_queue.h ipc/ipc_machdep.h ipc/ipc_marequest.c \
+       ipc/ipc_marequest.h ipc/ipc_mqueue.c ipc/ipc_mqueue.h \
+       ipc/ipc_notify.c ipc/ipc_notify.h ipc/ipc_object.c \
+       ipc/ipc_object.h ipc/ipc_port.c ipc/ipc_port.h ipc/ipc_print.h \
+       ipc/ipc_pset.c ipc/ipc_pset.h ipc/ipc_right.c ipc/ipc_right.h \
+       ipc/ipc_space.c ipc/ipc_space.h ipc/ipc_table.c \
+       ipc/ipc_table.h ipc/ipc_target.c ipc/ipc_target.h \
+       ipc/ipc_thread.c ipc/ipc_thread.h ipc/ipc_types.h \
+       ipc/mach_msg.c ipc/mach_msg.h ipc/mach_port.c ipc/mach_port.h \
+       ipc/mach_rpc.c ipc/mach_debug.c ipc/port.h kern/act.c \
+       kern/act.h kern/assert.h kern/ast.c kern/ast.h \
        kern/boot_script.h kern/bootstrap.c kern/bootstrap.h \
        kern/counters.c kern/counters.h kern/cpu_number.h kern/debug.c \
        kern/debug.h kern/eventcount.c kern/eventcount.h \
@@ -2569,22 +2567,22 @@ libkernel_a_SOURCES = $(am__append_2) ipc/ipc_entry.c 
ipc/ipc_entry.h \
        kern/kalloc.h kern/kern_types.h kern/list.h kern/lock.c \
        kern/lock.h kern/lock_mon.c kern/mach_clock.c \
        kern/mach_clock.h kern/mach_factor.c kern/mach_factor.h \
-       kern/machine.c kern/machine.h kern/macro_help.h \
-       kern/pc_sample.c kern/pc_sample.h kern/printf.c kern/printf.h \
-       kern/priority.c kern/priority.h kern/processor.c \
-       kern/processor.h kern/profile.c kern/queue.c kern/queue.h \
-       kern/rbtree.c kern/rbtree.h kern/rbtree_i.h kern/refcount.h \
-       kern/slab.c kern/slab.h kern/sched.h kern/sched_prim.c \
-       kern/sched_prim.h kern/shuttle.h kern/startup.c kern/startup.h \
-       kern/strings.c kern/syscall_emulation.c \
-       kern/syscall_emulation.h kern/syscall_subr.c \
-       kern/syscall_subr.h kern/syscall_sw.c kern/syscall_sw.h \
-       kern/task.c kern/task.h kern/thread.c kern/thread.h \
-       kern/thread_swap.c kern/thread_swap.h kern/time_stamp.c \
-       kern/time_stamp.h kern/timer.c kern/timer.h kern/xpr.c \
-       kern/xpr.h kern/elf-load.c kern/boot_script.c util/putchar.c \
-       util/putchar.h util/puts.c util/atoi.c util/atoi.h \
-       vm/memory_object_proxy.c vm/memory_object_proxy.h \
+       kern/machine.c kern/machine.h kern/macros.h kern/pc_sample.c \
+       kern/pc_sample.h kern/printf.c kern/printf.h kern/priority.c \
+       kern/priority.h kern/processor.c kern/processor.h \
+       kern/profile.c kern/queue.c kern/queue.h kern/rbtree.c \
+       kern/rbtree.h kern/rbtree_i.h kern/rdxtree.c kern/rdxtree.h \
+       kern/rdxtree_i.h kern/refcount.h kern/slab.c kern/slab.h \
+       kern/sched.h kern/sched_prim.c kern/sched_prim.h \
+       kern/shuttle.h kern/startup.c kern/startup.h kern/strings.c \
+       kern/syscall_emulation.c kern/syscall_emulation.h \
+       kern/syscall_subr.c kern/syscall_subr.h kern/syscall_sw.c \
+       kern/syscall_sw.h kern/task.c kern/task.h kern/thread.c \
+       kern/thread.h kern/thread_swap.c kern/thread_swap.h \
+       kern/time_stamp.c kern/time_stamp.h kern/timer.c kern/timer.h \
+       kern/xpr.c kern/xpr.h kern/elf-load.c kern/boot_script.c \
+       util/putchar.c util/putchar.h util/puts.c util/atoi.c \
+       util/atoi.h vm/memory_object_proxy.c vm/memory_object_proxy.h \
        vm/memory_object.c vm/memory_object.h vm/pmap.h vm/vm_debug.c \
        vm/vm_external.c vm/vm_external.h vm/vm_fault.c vm/vm_fault.h \
        vm/vm_init.c vm/vm_init.h vm/vm_kern.c vm/vm_kern.h \
@@ -2778,7 +2776,10 @@ liblinux_a_CPPFLAGS = $(AM_CPPFLAGS) \
 
 # Because of the use of `extern inline' in some Linux header files without
 # corresponding text segment definitions, we must always optimize.
-liblinux_a_CFLAGS = -O2 $(AM_CFLAGS)
+
+# See <http://lists.gnu.org/archive/html/bug-hurd/2006-01/msg00148.html>.
+liblinux_a_CFLAGS = -O2 $(AM_CFLAGS) -fno-strict-aliasing
+
 # TODO.  Do we really need `-traditional'?
 liblinux_a_CCASFLAGS = $(AM_CCASFLAGS) \
        -D__ASSEMBLY__ -traditional \
@@ -2915,6 +2916,7 @@ clib_routines := memcmp memcpy memmove                    
        \
                 htonl htons ntohl ntohs                        \
                 udivdi3 __udivdi3                              \
                 __rel_iplt_start __rel_iplt_end                \
+                __ffsdi2                                       \
                 _START _start etext _edata end _end # actually ld magic, not 
libc.
 
 gnumach_LINK = $(LD) $(LINKFLAGS) $(gnumach_LINKFLAGS) -o $@
@@ -3104,8 +3106,6 @@ ddb/db_write_cmd.$(OBJEXT): ddb/$(am__dirstamp) \
        ddb/$(DEPDIR)/$(am__dirstamp)
 ipc/ipc_entry.$(OBJEXT): ipc/$(am__dirstamp) \
        ipc/$(DEPDIR)/$(am__dirstamp)
-ipc/ipc_hash.$(OBJEXT): ipc/$(am__dirstamp) \
-       ipc/$(DEPDIR)/$(am__dirstamp)
 ipc/ipc_init.$(OBJEXT): ipc/$(am__dirstamp) \
        ipc/$(DEPDIR)/$(am__dirstamp)
 ipc/ipc_kmsg.$(OBJEXT): ipc/$(am__dirstamp) \
@@ -3126,8 +3126,6 @@ ipc/ipc_right.$(OBJEXT): ipc/$(am__dirstamp) \
        ipc/$(DEPDIR)/$(am__dirstamp)
 ipc/ipc_space.$(OBJEXT): ipc/$(am__dirstamp) \
        ipc/$(DEPDIR)/$(am__dirstamp)
-ipc/ipc_splay.$(OBJEXT): ipc/$(am__dirstamp) \
-       ipc/$(DEPDIR)/$(am__dirstamp)
 ipc/ipc_table.$(OBJEXT): ipc/$(am__dirstamp) \
        ipc/$(DEPDIR)/$(am__dirstamp)
 ipc/ipc_target.$(OBJEXT): ipc/$(am__dirstamp) \
@@ -3192,6 +3190,8 @@ kern/queue.$(OBJEXT): kern/$(am__dirstamp) \
        kern/$(DEPDIR)/$(am__dirstamp)
 kern/rbtree.$(OBJEXT): kern/$(am__dirstamp) \
        kern/$(DEPDIR)/$(am__dirstamp)
+kern/rdxtree.$(OBJEXT): kern/$(am__dirstamp) \
+       kern/$(DEPDIR)/$(am__dirstamp)
 kern/slab.$(OBJEXT): kern/$(am__dirstamp) \
        kern/$(DEPDIR)/$(am__dirstamp)
 kern/sched_prim.$(OBJEXT): kern/$(am__dirstamp) \
@@ -4233,7 +4233,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @address@hidden/xen/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/xen/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
address@hidden@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@@ -4244,7 +4243,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
address@hidden@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@@ -4292,6 +4290,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
address@hidden@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
 @AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@@ -7831,6 +7830,16 @@ uninstall-am: uninstall-dvi-am 
uninstall-exec_bootPROGRAMS \
          -list $*.user.msgids                                  \
          < $<
 
+vpath %.defs $(top_srcdir)
+
+# Stand-alone rule to generate the list of message ids when neither
+# the client nor the server stubs are required.
+%.msgids: %.defs
+       $(MIGCOM_V) $(CPP) $(AM_CPPFLAGS) $(CPPFLAGS) -E $<     \
+       | $(MIGCOM) $(MIGCOMFLAGS) $(MIGCOMSFLAGS)              \
+         -sheader /dev/null -server /dev/null                  \
+         -list "$*.msgids"
+
 # This is how it should be done, but this is not integrated into GNU Automake
 # and is missing automatic inter-file dependency management because of that.
 
@@ -7892,7 +7901,8 @@ echo-%:
 install-data-hook:
        rm -f '$(DESTDIR)$(include_machdir)'/machine
        ln -s '$(systype)' '$(DESTDIR)$(include_machdir)'/machine
-gnumach.msgids: $(filter %.msgids,$(nodist_libkernel_a_SOURCES))
+gnumach.msgids: $(filter %.msgids,$(nodist_libkernel_a_SOURCES)) \
+               ipc/notify.msgids
        $(AM_V_at) cat $^ > address@hidden
        $(AM_V_GEN) mv address@hidden $@
 dist-hook: dist-hook-linux
diff --git a/Makefrag.am b/Makefrag.am
index 9166143..b9d96c5 100644
--- a/Makefrag.am
+++ b/Makefrag.am
@@ -80,8 +80,6 @@ endif
 libkernel_a_SOURCES += \
        ipc/ipc_entry.c \
        ipc/ipc_entry.h \
-       ipc/ipc_hash.c \
-       ipc/ipc_hash.h \
        ipc/ipc_init.c \
        ipc/ipc_init.h \
        ipc/ipc_kmsg.c \
@@ -105,8 +103,6 @@ libkernel_a_SOURCES += \
        ipc/ipc_right.h \
        ipc/ipc_space.c \
        ipc/ipc_space.h \
-       ipc/ipc_splay.c \
-       ipc/ipc_splay.h \
        ipc/ipc_table.c \
        ipc/ipc_table.h \
        ipc/ipc_target.c \
@@ -122,7 +118,8 @@ libkernel_a_SOURCES += \
        ipc/mach_debug.c \
        ipc/port.h
 EXTRA_DIST += \
-       ipc/mach_port.srv
+       ipc/mach_port.srv \
+       ipc/notify.defs
 
 
 #
@@ -171,7 +168,7 @@ libkernel_a_SOURCES += \
        kern/mach_factor.h \
        kern/machine.c \
        kern/machine.h \
-       kern/macro_help.h \
+       kern/macros.h \
        kern/pc_sample.c \
        kern/pc_sample.h \
        kern/printf.c \
@@ -186,6 +183,9 @@ libkernel_a_SOURCES += \
        kern/rbtree.c \
        kern/rbtree.h \
        kern/rbtree_i.h \
+       kern/rdxtree.c \
+       kern/rdxtree.h \
+       kern/rdxtree_i.h \
        kern/refcount.h \
        kern/slab.c \
        kern/slab.h \
@@ -548,7 +548,8 @@ nodist_libkernel_a_SOURCES += \
 # rpctrace can make use of that.
 MOSTLYCLEANFILES += \
        gnumach.msgids
-gnumach.msgids: $(filter %.msgids,$(nodist_libkernel_a_SOURCES))
+gnumach.msgids: $(filter %.msgids,$(nodist_libkernel_a_SOURCES)) \
+               ipc/notify.msgids
        $(AM_V_at) cat $^ > address@hidden
        $(AM_V_GEN) mv address@hidden $@
 # `exec_' prefix, so that we don't try to build that file during when running
diff --git a/Makerules.mig.am b/Makerules.mig.am
index 3060984..085b247 100644
--- a/Makerules.mig.am
+++ b/Makerules.mig.am
@@ -88,6 +88,16 @@ lib_dep_tr_for_defs_a_CPPFLAGS = $(AM_CPPFLAGS) \
          -list $*.user.msgids                                  \
          < $<
 
+vpath %.defs $(top_srcdir)
+
+# Stand-alone rule to generate the list of message ids when neither
+# the client nor the server stubs are required.
+%.msgids: %.defs
+       $(MIGCOM_V) $(CPP) $(AM_CPPFLAGS) $(CPPFLAGS) -E $<     \
+       | $(MIGCOM) $(MIGCOMFLAGS) $(MIGCOMSFLAGS)              \
+         -sheader /dev/null -server /dev/null                  \
+         -list "$*.msgids"
+
 # This is how it should be done, but this is not integrated into GNU Automake
 # and is missing automatic inter-file dependency management because of that.
 
diff --git a/NEWS b/NEWS
index 357b23f..5d220fa 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,4 @@
-2014-XX-XX
-Version 1.5
+Version 1.5 (2015-04-10)
 
 Numerous cleanups and stylistic fixes of the code base.  Several
 problems have been identified using static analysis tools and
@@ -18,8 +17,7 @@ The vm pageout policy has been tuned to accommodate modern 
hardware.
 The kernel gained partial ACPI support on x86, enough to power down
 the system.
 
-2013-09-27
-Version 1.4
+Version 1.4 (2013-09-27)
 
 Really too many to list them individually.  Highlight include numerous bug and
 stability fixes, a Xen port for 32-bit x86 including basic support for Physical
diff --git a/config.h.in b/config.h.in
index 1afe5a6..aff1fa6 100644
--- a/config.h.in
+++ b/config.h.in
@@ -425,6 +425,9 @@
 /* CPU_L1_SHIFT */
 #undef CPU_L1_SHIFT
 
+/* ENABLE_IMMEDIATE_CONSOLE */
+#undef ENABLE_IMMEDIATE_CONSOLE
+
 /* FAST_TAS */
 #undef FAST_TAS
 
diff --git a/configfrag.ac b/configfrag.ac
index 5f13b63..5df6239 100644
--- a/configfrag.ac
+++ b/configfrag.ac
@@ -142,7 +142,7 @@ AC_ARG_ENABLE([kmsg],
 # `${file}' and `$file' have different meanings here with respect to having the
 # files in the referenced directory considered for `make dist' or not.  See
 # <http://lists.gnu.org/archive/html/bug-automake/2006-11/msg00027.html>.
-AC_CONFIG_LINKS([machine:$systype/$systype
+AC_CONFIG_LINKS([machine:$srcdir/$systype/$systype
                 mach/machine:$systype/include/mach/$systype])
 
 dnl Local Variables:
diff --git a/configure b/configure
index ca308b9..a0c1fb2 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for GNU Mach 1.4+git20150409.
+# Generated by GNU Autoconf 2.69 for GNU Mach 1.4+git20150704.
 #
 # Report bugs to <address@hidden>.
 #
@@ -579,8 +579,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='GNU Mach'
 PACKAGE_TARNAME='gnumach'
-PACKAGE_VERSION='1.4+git20150409'
-PACKAGE_STRING='GNU Mach 1.4+git20150409'
+PACKAGE_VERSION='1.4+git20150704'
+PACKAGE_STRING='GNU Mach 1.4+git20150704'
 PACKAGE_BUGREPORT='address@hidden'
 PACKAGE_URL=''
 
@@ -1584,7 +1584,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures GNU Mach 1.4+git20150409 to adapt to many kinds of 
systems.
+\`configure' configures GNU Mach 1.4+git20150704 to adapt to many kinds of 
systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1654,7 +1654,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of GNU Mach 1.4+git20150409:";;
+     short | recursive ) echo "Configuration of GNU Mach 1.4+git20150704:";;
    esac
   cat <<\_ACEOF
 
@@ -2002,7 +2002,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-GNU Mach configure 1.4+git20150409
+GNU Mach configure 1.4+git20150704
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2094,7 +2094,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by GNU Mach $as_me 1.4+git20150409, which was
+It was created by GNU Mach $as_me 1.4+git20150704, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2960,7 +2960,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='gnumach'
- VERSION='1.4+git20150409'
+ VERSION='1.4+git20150704'
 
 
 # Some tools Automake needs.
@@ -6240,6 +6240,12 @@ _ACEOF
 # Options.
 #
 
+# The immediate console, useful for debugging early system
+# initialization.  Disabled by default.
+
+$as_echo "#define ENABLE_IMMEDIATE_CONSOLE 0" >>confdefs.h
+
+
 # Check whether --enable-lpr was given.
 if test "${enable_lpr+set}" = set; then :
   enableval=$enable_lpr;
@@ -6556,7 +6562,7 @@ fi
 # `${file}' and `$file' have different meanings here with respect to having the
 # files in the referenced directory considered for `make dist' or not.  See
 # <http://lists.gnu.org/archive/html/bug-automake/2006-11/msg00027.html>.
-ac_config_links="$ac_config_links machine:$systype/$systype 
mach/machine:$systype/include/mach/$systype"
+ac_config_links="$ac_config_links machine:$srcdir/$systype/$systype 
mach/machine:$systype/include/mach/$systype"
 
 
 
@@ -12110,7 +12116,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by GNU Mach $as_me 1.4+git20150409, which was
+This file was extended by GNU Mach $as_me 1.4+git20150704, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -12181,7 +12187,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-GNU Mach config.status 1.4+git20150409
+GNU Mach config.status 1.4+git20150704
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -12312,7 +12318,7 @@ do
   case $ac_config_target in
     "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
     "tests/test-mbchk") CONFIG_FILES="$CONFIG_FILES tests/test-mbchk" ;;
-    "machine") CONFIG_LINKS="$CONFIG_LINKS machine:$systype/$systype" ;;
+    "machine") CONFIG_LINKS="$CONFIG_LINKS machine:$srcdir/$systype/$systype" 
;;
     "mach/machine") CONFIG_LINKS="$CONFIG_LINKS 
mach/machine:$systype/include/mach/$systype" ;;
     "linux/src/include/asm") CONFIG_LINKS="$CONFIG_LINKS 
linux/src/include/asm:linux/src/include/asm-$systype" ;;
     "linux/dev/include/asm") CONFIG_LINKS="$CONFIG_LINKS 
linux/dev/include/asm:linux/dev/include/asm-$systype" ;;
diff --git a/ddb/db_print.c b/ddb/db_print.c
index 24a3e33..fb4efaa 100644
--- a/ddb/db_print.c
+++ b/ddb/db_print.c
@@ -439,17 +439,11 @@ db_port_iterate(thread, func)
        void (*func)();
 {
        ipc_entry_t entry;
-       int index;
        int n = 0;
-       int size;
-       ipc_space_t space;
-
-       space = thread->task->itk_space;
-       entry = space->is_table;
-       size = space->is_table_size;
-       for (index = 0; index < size; index++, entry++) {
+       struct rdxtree_iter iter;
+       rdxtree_for_each(&thread->task->itk_space->is_map, &iter, entry) {
            if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
-               (*func)(index, (ipc_port_t) entry->ie_object,
+               (*func)(entry->ie_name, (ipc_port_t) entry->ie_object,
                        entry->ie_bits, n++);
        }
        return(n);
@@ -460,16 +454,14 @@ db_lookup_port(
        thread_t        thread,
        int             id)
 {
-       ipc_space_t space;
        ipc_entry_t entry;
 
        if (thread == THREAD_NULL)
            return(0);
-       space = thread->task->itk_space;
-       if (id < 0 || id >= space->is_table_size)
+       if (id < 0)
            return(0);
-       entry = &space->is_table[id];
-       if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
+       entry = ipc_entry_lookup(thread->task->itk_space, (mach_port_t) id);
+       if (entry && entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
            return((ipc_port_t)entry->ie_object);
        return(0);
 }
diff --git a/ddb/db_trap.c b/ddb/db_trap.c
index b56ffdc..7e10731 100644
--- a/ddb/db_trap.c
+++ b/ddb/db_trap.c
@@ -44,6 +44,7 @@
 #include <ddb/db_task_thread.h>
 #include <ddb/db_trap.h>
 #include <ddb/db_run.h>
+#include <machine/db_interface.h>
 
 
 extern jmp_buf_t *db_recover;
@@ -88,6 +89,9 @@ db_task_trap(
                db_print_loc_and_inst(db_dot, task_space);
            else
                db_printf("Trouble printing location %#X.\n", db_dot);
+
+           if (!bkpt && !watchpt && _setjmp(db_recover = &db_jmpbuf) == 0)
+             db_stack_trace_cmd(0, 0, -1, "");
            db_recover = prev;
 
            db_command_loop();
diff --git a/device/blkio.c b/device/blkio.c
index ee86634..e5b4d09 100644
--- a/device/blkio.c
+++ b/device/blkio.c
@@ -101,7 +101,7 @@ void minphys(io_req_t ior)
  * Dummy routine placed in device switch entries to indicate that
  * block device may be mapped.
  */
-vm_offset_t block_io_mmap(void)
+int block_io_mmap(dev_t dev, vm_offset_t off, int prot)
 {
        return (0);
 }
diff --git a/device/blkio.h b/device/blkio.h
index 13a1669..77eb105 100644
--- a/device/blkio.h
+++ b/device/blkio.h
@@ -19,6 +19,6 @@
 #ifndef _DEVICE_BLKIO_H_
 #define _DEVICE_BLKIO_H_
 
-extern vm_offset_t block_io_mmap(void);
+extern int block_io_mmap(dev_t dev, vm_offset_t off, int prot);
 
 #endif /* _DEVICE_BLKIO_H_ */
diff --git a/device/cons.h b/device/cons.h
index 8ac796c..34f3bc5 100644
--- a/device/cons.h
+++ b/device/cons.h
@@ -54,4 +54,15 @@ extern int cngetc(void);
 extern int cnmaygetc(void);
 
 extern void cnputc(char);
+
+/*
+ * ROM getc/putc primitives.
+ * On some architectures, the boot ROM provides basic character input/output
+ * routines that can be used before devices are configured or virtual memory
+ * is enabled.  This can be useful to debug (or catch panics from) code early
+ * in the bootstrap procedure.
+ */
+extern int     (*romgetc)(char c);
+extern void    (*romputc)(char c);
+
 #endif /* _DEVICE_CONS_H */
diff --git a/device/dev_master.h b/device/dev_master.h
index 6ad1152..70d4c63 100644
--- a/device/dev_master.h
+++ b/device/dev_master.h
@@ -37,7 +37,7 @@
 
 #if    NCPUS > 1
 
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 #include <kern/cpu_number.h>
 #include <kern/sched_prim.h>
 #include <kern/thread.h>
diff --git a/device/ds_routines.c b/device/ds_routines.c
index 38d773c..43ed5b5 100644
--- a/device/ds_routines.c
+++ b/device/ds_routines.c
@@ -417,12 +417,11 @@ mach_convert_device_to_port (mach_device_t device)
 }
 
 static io_return_t
-device_open(reply_port, reply_port_type, mode, name, device_p)
-       const ipc_port_t reply_port;
-       mach_msg_type_name_t reply_port_type;
-       dev_mode_t      mode;
-       char *          name;
-       device_t        *device_p;      /* out */
+device_open(const ipc_port_t   reply_port,
+           mach_msg_type_name_t reply_port_type,
+           dev_mode_t          mode,
+           char *              name,
+           device_t            *device_p)
 {
        mach_device_t           device;
        kern_return_t           result;
@@ -537,8 +536,7 @@ device_open(reply_port, reply_port_type, mode, name, 
device_p)
 }
 
 boolean_t
-ds_open_done(ior)
-       const io_req_t          ior;
+ds_open_done(const io_req_t ior)
 {
        kern_return_t           result;
        mach_device_t           device;
@@ -597,8 +595,10 @@ ds_open_done(ior)
 }
 
 static io_return_t
-device_close(mach_device_t device)
+device_close(void *dev)
 {
+       mach_device_t device = dev;
+
        device_lock(device);
 
        /*
@@ -659,17 +659,16 @@ device_close(mach_device_t device)
  * Write to a device.
  */
 static io_return_t
-device_write(device, reply_port, reply_port_type, mode, recnum,
-            data, data_count, bytes_written)
-       mach_device_t           device;
-       const ipc_port_t        reply_port;
-       mach_msg_type_name_t    reply_port_type;
-       dev_mode_t              mode;
-       recnum_t                recnum;
-       const io_buf_ptr_t      data;
-       unsigned int            data_count;
-       int                     *bytes_written; /* out */
+device_write(void *dev,
+            const ipc_port_t   reply_port,
+            mach_msg_type_name_t       reply_port_type,
+            dev_mode_t         mode,
+            recnum_t           recnum,
+            const io_buf_ptr_t data,
+            unsigned int       data_count,
+            int                *bytes_written)
 {
+       mach_device_t           device = dev;
        io_req_t                ior;
        io_return_t             result;
 
@@ -750,17 +749,16 @@ device_write(device, reply_port, reply_port_type, mode, 
recnum,
  * Write to a device, but memory is in message.
  */
 static io_return_t
-device_write_inband(device, reply_port, reply_port_type, mode, recnum,
-                   data, data_count, bytes_written)
-       mach_device_t           device;
-       const ipc_port_t        reply_port;
-       mach_msg_type_name_t    reply_port_type;
-       dev_mode_t              mode;
-       recnum_t                recnum;
-       io_buf_ptr_inband_t     data;
-       unsigned int            data_count;
-       int                     *bytes_written; /* out */
+device_write_inband(void               *dev,
+                   const ipc_port_t    reply_port,
+                   mach_msg_type_name_t        reply_port_type,
+                   dev_mode_t          mode,
+                   recnum_t            recnum,
+                   io_buf_ptr_inband_t data,
+                   unsigned int        data_count,
+                   int                 *bytes_written)
 {
+       mach_device_t           device = dev;
        io_req_t                ior;
        io_return_t             result;
 
@@ -1018,8 +1016,7 @@ device_write_dealloc(io_req_t ior)
  * Send write completion message to client, and discard the data.
  */
 boolean_t
-ds_write_done(ior)
-       const io_req_t          ior;
+ds_write_done(const io_req_t ior)
 {
        /*
         *      device_write_dealloc discards the data that has been
@@ -1064,17 +1061,16 @@ ds_write_done(ior)
  * Read from a device.
  */
 static io_return_t
-device_read(device, reply_port, reply_port_type, mode, recnum,
-           bytes_wanted, data, data_count)
-       mach_device_t           device;
-       const ipc_port_t        reply_port;
-       mach_msg_type_name_t    reply_port_type;
-       dev_mode_t              mode;
-       recnum_t                recnum;
-       int                     bytes_wanted;
-       io_buf_ptr_t            *data;          /* out */
-       unsigned int            *data_count;    /* out */
+device_read(void *dev,
+           const ipc_port_t    reply_port,
+           mach_msg_type_name_t        reply_port_type,
+           dev_mode_t          mode,
+           recnum_t            recnum,
+           int                 bytes_wanted,
+           io_buf_ptr_t        *data,
+           unsigned int        *data_count)
 {
+       mach_device_t           device = dev;
        io_req_t                ior;
        io_return_t             result;
 
@@ -1141,17 +1137,16 @@ device_read(device, reply_port, reply_port_type, mode, 
recnum,
  * Read from a device, but return the data 'inband.'
  */
 static io_return_t
-device_read_inband(device, reply_port, reply_port_type, mode, recnum,
-                  bytes_wanted, data, data_count)
-       mach_device_t           device;
-       const ipc_port_t        reply_port;
-       mach_msg_type_name_t    reply_port_type;
-       dev_mode_t              mode;
-       recnum_t                recnum;
-       int                     bytes_wanted;
-       char                    *data;          /* pointer to OUT array */
-       unsigned int            *data_count;    /* out */
+device_read_inband(void                        *dev,
+                  const ipc_port_t     reply_port,
+                  mach_msg_type_name_t reply_port_type,
+                  dev_mode_t           mode,
+                  recnum_t             recnum,
+                  int                  bytes_wanted,
+                  char                 *data,
+                  unsigned int         *data_count)
 {
+       mach_device_t           device = dev;
        io_req_t                ior;
        io_return_t             result;
 
@@ -1248,8 +1243,7 @@ kern_return_t device_read_alloc(
        return (KERN_SUCCESS);
 }
 
-boolean_t ds_read_done(ior)
-       const io_req_t  ior;
+boolean_t ds_read_done(const io_req_t ior)
 {
        vm_offset_t             start_data, end_data;
        vm_offset_t             start_sent, end_sent;
@@ -1345,11 +1339,12 @@ boolean_t ds_read_done(ior)
 
 static io_return_t
 device_set_status(
-       mach_device_t           device,
+       void                    *dev,
        dev_flavor_t            flavor,
        dev_status_t            status,
        mach_msg_type_number_t  status_count)
 {
+       mach_device_t           device = dev;
        if (device->state != DEV_STATE_OPEN)
            return (D_NO_SUCH_DEVICE);
 
@@ -1363,11 +1358,12 @@ device_set_status(
 
 io_return_t
 mach_device_get_status(
-       mach_device_t           device,
+       void                    *dev,
        dev_flavor_t            flavor,
        dev_status_t            status,         /* pointer to OUT array */
        mach_msg_type_number_t  *status_count)  /* out */
 {
+       mach_device_t           device = dev;
        if (device->state != DEV_STATE_OPEN)
            return (D_NO_SUCH_DEVICE);
 
@@ -1380,13 +1376,13 @@ mach_device_get_status(
 }
 
 static io_return_t
-device_set_filter(device, receive_port, priority, filter, filter_count)
-       mach_device_t           device;
-       const ipc_port_t        receive_port;
-       int                     priority;
-       filter_t                filter[];       /* pointer to IN array */
-       unsigned int            filter_count;
+device_set_filter(void                 *dev,
+                 const ipc_port_t      receive_port,
+                 int                   priority,
+                 filter_t              filter[],
+                 unsigned int          filter_count)
 {
+       mach_device_t           device = dev;
        if (device->state != DEV_STATE_OPEN)
            return (D_NO_SUCH_DEVICE);
 
@@ -1407,13 +1403,14 @@ device_set_filter(device, receive_port, priority, 
filter, filter_count)
 
 static io_return_t
 device_map(
-       mach_device_t           device,
+       void                    *dev,
        vm_prot_t               protection,
        vm_offset_t             offset,
        vm_size_t               size,
        ipc_port_t              *pager, /* out */
        boolean_t               unmap)  /* ? */
 {
+       mach_device_t           device = dev;
        if (protection & ~VM_PROT_ALL)
                return (KERN_INVALID_ARGUMENT);
 
@@ -1430,8 +1427,7 @@ device_map(
  * Doesn't do anything (yet).
  */
 static void
-ds_no_senders(notification)
-       const mach_no_senders_notification_t *notification;
+ds_no_senders(mach_no_senders_notification_t *notification)
 {
        printf("ds_no_senders called! device_port=0x%lx count=%d\n",
               notification->not_header.msgh_remote_port,
diff --git a/device/io_req.h b/device/io_req.h
index 65e23e6..1ad4680 100644
--- a/device/io_req.h
+++ b/device/io_req.h
@@ -42,7 +42,7 @@
 #include <device/device_types.h>
 #include <device/dev_hdr.h>
 
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 
 /*
  * IO request element, queued on device for delayed replies.
diff --git a/device/net_io.h b/device/net_io.h
index f6de854..d4e24d4 100644
--- a/device/net_io.h
+++ b/device/net_io.h
@@ -38,7 +38,7 @@
 #include <mach/machine/vm_types.h>
 #include <ipc/ipc_kmsg.h>
 
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 #include <kern/lock.h>
 #include <kern/kalloc.h>
 
diff --git a/doc/mach.info b/doc/mach.info
index 7949c59..1a5560b 100644
--- a/doc/mach.info
+++ b/doc/mach.info
@@ -3,7 +3,7 @@ This is mach.info, produced by makeinfo version 5.2 from 
mach.texi.
 This file documents the GNU Mach microkernel.
 
    This is edition 0.4, last updated on 11 March 2015, of 'The GNU Mach
-Reference Manual', for version 1.4+git20150409.
+Reference Manual', for version 1.4+git20150704.
 
    Copyright (C) 2001, 2002, 2006, 2007, 2008 Free Software Foundation,
 Inc.
diff --git a/doc/mach.info-1 b/doc/mach.info-1
index 2b6a3d9..c689156 100644
--- a/doc/mach.info-1
+++ b/doc/mach.info-1
@@ -3,7 +3,7 @@ This is mach.info, produced by makeinfo version 5.2 from 
mach.texi.
 This file documents the GNU Mach microkernel.
 
    This is edition 0.4, last updated on 11 March 2015, of 'The GNU Mach
-Reference Manual', for version 1.4+git20150409.
+Reference Manual', for version 1.4+git20150704.
 
    Copyright (C) 2001, 2002, 2006, 2007, 2008 Free Software Foundation,
 Inc.
@@ -46,7 +46,7 @@ Main Menu
 This file documents the GNU Mach microkernel.
 
    This is edition 0.4, last updated on 11 March 2015, of 'The GNU Mach
-Reference Manual', for version 1.4+git20150409.
+Reference Manual', for version 1.4+git20150704.
 
    Copyright (C) 2001, 2002, 2006, 2007, 2008 Free Software Foundation,
 Inc.
diff --git a/doc/mach.info-2 b/doc/mach.info-2
index 395d220..6f3b233 100644
--- a/doc/mach.info-2
+++ b/doc/mach.info-2
@@ -3,7 +3,7 @@ This is mach.info, produced by makeinfo version 5.2 from 
mach.texi.
 This file documents the GNU Mach microkernel.
 
    This is edition 0.4, last updated on 11 March 2015, of 'The GNU Mach
-Reference Manual', for version 1.4+git20150409.
+Reference Manual', for version 1.4+git20150704.
 
    Copyright (C) 2001, 2002, 2006, 2007, 2008 Free Software Foundation,
 Inc.
diff --git a/doc/stamp-vti b/doc/stamp-vti
index be76cb6..5bdb050 100644
--- a/doc/stamp-vti
+++ b/doc/stamp-vti
@@ -1,4 +1,4 @@
 @set UPDATED 11 March 2015
 @set UPDATED-MONTH March 2015
address@hidden EDITION 1.4+git20150409
address@hidden VERSION 1.4+git20150409
address@hidden EDITION 1.4+git20150704
address@hidden VERSION 1.4+git20150704
diff --git a/doc/version.texi b/doc/version.texi
index be76cb6..5bdb050 100644
--- a/doc/version.texi
+++ b/doc/version.texi
@@ -1,4 +1,4 @@
 @set UPDATED 11 March 2015
 @set UPDATED-MONTH March 2015
address@hidden EDITION 1.4+git20150409
address@hidden VERSION 1.4+git20150409
address@hidden EDITION 1.4+git20150704
address@hidden VERSION 1.4+git20150704
diff --git a/i386/configfrag.ac b/i386/configfrag.ac
index 1eaabca..48744b1 100644
--- a/i386/configfrag.ac
+++ b/i386/configfrag.ac
@@ -73,6 +73,10 @@ AC_DEFINE_UNQUOTED([NLPR], [$nlpr], [NLPR])
 # Options.
 #
 
+# The immediate console, useful for debugging early system
+# initialization.  Disabled by default.
+AC_DEFINE([ENABLE_IMMEDIATE_CONSOLE], [0], [ENABLE_IMMEDIATE_CONSOLE])
+
 AC_ARG_ENABLE([lpr],
   AS_HELP_STRING([--enable-lpr], [lpr device; on ix86-at enabled by default]))
 [case $host_platform:$host_cpu in
diff --git a/i386/grub/misc.h b/i386/grub/misc.h
index c6cd456..b71140a 100644
--- a/i386/grub/misc.h
+++ b/i386/grub/misc.h
@@ -21,6 +21,7 @@
 #define GRUB_MISC_HEADER       1
 
 #include <stdarg.h>
+#include <kern/macros.h>
 #include <grub/types.h>
 #include <grub/symbol.h>
 #include <grub/err.h>
@@ -32,7 +33,6 @@
 #define ALIGN_UP_OVERHEAD(addr, align) ((-(addr)) & ((typeof (addr)) (align) - 
1))
 #define ALIGN_DOWN(addr, align) \
        ((addr) & ~((typeof (addr)) align - 1))
-#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
 #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; }
 
 #define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, 
condition, __VA_ARGS__)
diff --git a/i386/i386/db_trace.c b/i386/i386/db_trace.c
index cdebde1..ec33859 100644
--- a/i386/i386/db_trace.c
+++ b/i386/i386/db_trace.c
@@ -488,7 +488,7 @@ db_i386_stack_trace(
                db_printf("...");
            db_printf(")");
            if (offset) {
-               db_printf("+%x", offset);
+               db_printf("+0x%x", offset);
             }
            if (db_line_at_pc(0, &filename, &linenum, callpc)) {
                db_printf(" [%s", filename);
diff --git a/i386/i386/pcb.c b/i386/i386/pcb.c
index e8040c8..3a0eba0 100644
--- a/i386/i386/pcb.c
+++ b/i386/i386/pcb.c
@@ -96,7 +96,7 @@ void stack_attach(
        /*
         *      Point top of kernel stack to user`s registers.
         */
-       STACK_IEL(stack)->saved_state = &thread->pcb->iss;
+       STACK_IEL(stack)->saved_state = USER_REGS(thread);
 }
 
 /*
@@ -193,8 +193,14 @@ void switch_ktss(pcb_t pcb)
        for (i=0; i < USER_GDT_SLOTS; i++) {
            if (memcmp(gdt_desc_p (mycpu, USER_GDT + (i << 3)),
                &pcb->ims.user_gdt[i], sizeof pcb->ims.user_gdt[i])) {
+               union {
+                       struct real_descriptor real_descriptor;
+                       uint64_t descriptor;
+               } user_gdt;
+               user_gdt.real_descriptor = pcb->ims.user_gdt[i];
+
                if (hyp_do_update_descriptor(kv_to_ma(gdt_desc_p (mycpu, 
USER_GDT + (i << 3))),
-                       *(uint64_t *) &pcb->ims.user_gdt[i]))
+                       user_gdt.descriptor))
                    panic("couldn't set user gdt %d\n",i);
            }
        }
@@ -298,7 +304,7 @@ void stack_handoff(
         *      user registers.
         */
 
-       STACK_IEL(stack)->saved_state = &new->pcb->iss;
+       STACK_IEL(stack)->saved_state = USER_REGS(new);
 
 }
 
diff --git a/i386/i386/phys.c b/i386/i386/phys.c
index 3af508f..d55bdd9 100644
--- a/i386/i386/phys.c
+++ b/i386/i386/phys.c
@@ -52,8 +52,9 @@ pmap_zero_page(vm_offset_t p)
        assert(p != vm_page_fictitious_addr);
        vm_offset_t v;
        pmap_mapwindow_t *map;
+       boolean_t mapped = p >= phys_last_addr;
 
-       if (p >= phys_last_addr)
+       if (mapped)
        {
                map = pmap_get_mapwindow(INTEL_PTE_W(p));
                v = map->vaddr;
@@ -63,7 +64,7 @@ pmap_zero_page(vm_offset_t p)
 
        memset((void*) v, 0, PAGE_SIZE);
 
-       if (p >= phys_last_addr)
+       if (mapped)
                pmap_put_mapwindow(map);
 }
 
@@ -77,10 +78,12 @@ pmap_copy_page(
 {
        vm_offset_t src_addr_v, dst_addr_v;
        pmap_mapwindow_t *src_map, *dst_map;
+       boolean_t src_mapped = src >= phys_last_addr;
+       boolean_t dst_mapped = dst >= phys_last_addr;
        assert(src != vm_page_fictitious_addr);
        assert(dst != vm_page_fictitious_addr);
 
-       if (src >= phys_last_addr)
+       if (src_mapped)
        {
                src_map = pmap_get_mapwindow(INTEL_PTE_R(src));
                src_addr_v = src_map->vaddr;
@@ -88,7 +91,7 @@ pmap_copy_page(
        else
                src_addr_v = phystokv(src);
 
-       if (dst >= phys_last_addr)
+       if (dst_mapped)
        {
                dst_map = pmap_get_mapwindow(INTEL_PTE_W(dst));
                dst_addr_v = dst_map->vaddr;
@@ -98,9 +101,9 @@ pmap_copy_page(
 
        memcpy((void *) dst_addr_v, (void *) src_addr_v, PAGE_SIZE);
 
-       if (src >= phys_last_addr)
+       if (src_mapped)
                pmap_put_mapwindow(src_map);
-       if (dst >= phys_last_addr)
+       if (dst_mapped)
                pmap_put_mapwindow(dst_map);
 }
 
@@ -117,10 +120,11 @@ copy_to_phys(
 {
        vm_offset_t dst_addr_v;
        pmap_mapwindow_t *dst_map;
+       boolean_t mapped = dst_addr_p >= phys_last_addr;
        assert(dst_addr_p != vm_page_fictitious_addr);
        assert(pa_to_pte(dst_addr_p + count-1) == pa_to_pte(dst_addr_p));
 
-       if (dst_addr_p >= phys_last_addr)
+       if (mapped)
        {
                dst_map = pmap_get_mapwindow(INTEL_PTE_W(dst_addr_p));
                dst_addr_v = dst_map->vaddr;
@@ -130,7 +134,7 @@ copy_to_phys(
 
        memcpy((void *)dst_addr_v, (void *)src_addr_v, count);
 
-       if (dst_addr_p >= phys_last_addr)
+       if (mapped)
                pmap_put_mapwindow(dst_map);
 }
 
@@ -148,10 +152,11 @@ copy_from_phys(
 {
        vm_offset_t src_addr_v;
        pmap_mapwindow_t *src_map;
+       boolean_t mapped = src_addr_p >= phys_last_addr;
        assert(src_addr_p != vm_page_fictitious_addr);
        assert(pa_to_pte(src_addr_p + count-1) == pa_to_pte(src_addr_p));
 
-       if (src_addr_p >= phys_last_addr)
+       if (mapped)
        {
                src_map = pmap_get_mapwindow(INTEL_PTE_R(src_addr_p));
                src_addr_v = src_map->vaddr;
@@ -161,7 +166,7 @@ copy_from_phys(
 
        memcpy((void *)dst_addr_v, (void *)src_addr_v, count);
 
-       if (src_addr_p >= phys_last_addr)
+       if (mapped)
                pmap_put_mapwindow(src_map);
 }
 
diff --git a/i386/i386/xen.h b/i386/i386/xen.h
index 638d671..c681187 100644
--- a/i386/i386/xen.h
+++ b/i386/i386/xen.h
@@ -21,6 +21,7 @@
 
 #ifdef MACH_XEN
 #ifndef        __ASSEMBLER__
+#include <kern/macros.h>
 #include <kern/printf.h>
 #include <mach/machine/vm_types.h>
 #include <mach/vm_param.h>
@@ -32,7 +33,6 @@
 #include <xen/public/xen.h>
 
 /* TODO: this should be moved in appropriate non-Xen place.  */
-#define barrier() __asm__ __volatile__ ("": : :"memory")
 #define mb() __asm__ __volatile__("lock; addl $0,0(%%esp)":::"memory")
 #define rmb() mb()
 #define wmb() mb()
diff --git a/i386/i386at/conf.c b/i386/i386at/conf.c
index ab4f680..fe7c7c0 100644
--- a/i386/i386at/conf.c
+++ b/i386/i386at/conf.c
@@ -87,6 +87,12 @@ struct dev_ops       dev_name_list[] =
          nodev },
 
 #ifndef        MACH_HYP
+#if    ENABLE_IMMEDIATE_CONSOLE
+       { "immc",       nulldev_open,   nulldev_close,  nulldev_read,
+         nulldev_write,        nulldev_getstat,        nulldev_setstat,
+         nomap,        nodev,  nulldev,        nulldev_portdeath,      0,
+         nodev },
+#endif /* ENABLE_IMMEDIATE_CONSOLE */
        { kdname,       kdopen,         kdclose,        kdread,
          kdwrite,      kdgetstat,      kdsetstat,      kdmmap,
          nodev,        nulldev,        kdportdeath,    0,
diff --git a/i386/i386at/cons_conf.c b/i386/i386at/cons_conf.c
index cf42bb6..1d7dd38 100644
--- a/i386/i386at/cons_conf.c
+++ b/i386/i386at/cons_conf.c
@@ -39,6 +39,10 @@
 #endif
 #endif /* MACH_HYP */
 
+#if    ENABLE_IMMEDIATE_CONSOLE
+#include "immc.h"
+#endif /* ENABLE_IMMEDIATE_CONSOLE */
+
 /*
  * The rest of the consdev fields are filled in by the respective
  * cnprobe routine.
@@ -47,6 +51,9 @@ struct        consdev constab[] = {
 #ifdef MACH_HYP
        {"hyp", hypcnprobe,     hypcninit,      hypcngetc,      hypcnputc},
 #else  /* MACH_HYP */
+#if    ENABLE_IMMEDIATE_CONSOLE
+       {"immc", immc_cnprobe,  immc_cninit,    immc_cngetc,    immc_cnputc},
+#endif /* ENABLE_IMMEDIATE_CONSOLE */
        {"kd",  kdcnprobe,      kdcninit,       kdcngetc,       kdcnputc},
 #if NCOM > 0
        {"com", comcnprobe,     comcninit,      comcngetc,      comcnputc},
diff --git a/i386/i386at/immc.c b/i386/i386at/immc.c
index e0837f2..ea95169 100644
--- a/i386/i386at/immc.c
+++ b/i386/i386at/immc.c
@@ -21,8 +21,11 @@
  *      Author: Bryan Ford, University of Utah CSL
  */
 
-#ifdef ENABLE_IMMEDIATE_CONSOLE
+#if    ENABLE_IMMEDIATE_CONSOLE
 
+#include <device/cons.h>
+#include <mach/boolean.h>
+#include <i386/vm_param.h>
 #include <string.h>
 
 /* This is a special "feature" (read: kludge)
@@ -35,22 +38,65 @@
 
 boolean_t immediate_console_enable = TRUE;
 
-void
-immc_cnputc(unsigned char c)
+/*
+ * XXX we assume that pcs *always* have a console
+ */
+int
+immc_cnprobe(struct consdev *cp)
+{
+       int maj, unit, pri;
+
+       maj = 0;
+       unit = 0;
+       pri = CN_INTERNAL;
+
+       cp->cn_dev = makedev(maj, unit);
+       cp->cn_pri = pri;
+       return 0;
+}
+
+int
+immc_cninit(struct consdev *cp)
+{
+       return 0;
+}
+
+int immc_cnmaygetc(void)
+{
+       return -1;
+}
+
+int
+immc_cngetc(dev_t dev, int wait)
+{
+       if (wait) {
+               int c;
+               while ((c = immc_cnmaygetc()) < 0)
+                       continue;
+               return c;
+       }
+       else
+               return immc_cnmaygetc();
+}
+
+int
+immc_cnputc(dev_t dev, int c)
 {
        static int ofs = -1;
 
        if (!immediate_console_enable)
-               return;
+               return -1;
        if (ofs < 0)
        {
                ofs = 0;
-               immc_cnputc('\n');
+               immc_cnputc(dev, '\n');
        }
-       else if (c == '\n')
+
+       if (c == '\n')
        {
-               memmove((void *)0xb8000, (void *)0xb8000+80*2, 80*2*24);
-               memset((void *)(0xb8000+80*2*24), 0, 80*2);
+               memmove((void *) phystokv(0xb8000),
+                       (void *) phystokv(0xb8000+80*2), 80*2*24);
+               memset((void *) phystokv((0xb8000+80*2*24)), 0, 80*2);
                ofs = 0;
        }
        else
@@ -59,20 +105,22 @@ immc_cnputc(unsigned char c)
 
                if (ofs >= 80)
                {
-                       immc_cnputc('\r');
-                       immc_cnputc('\n');
+                       immc_cnputc(dev, '\r');
+                       immc_cnputc(dev, '\n');
                }
 
-               p = (void*)0xb8000 + 80*2*24 + ofs*2;
+               p = (void *) phystokv(0xb8000 + 80*2*24 + ofs*2);
                p[0] = c;
                p[1] = 0x0f;
                ofs++;
        }
+       return 0;
 }
 
-int immc_cnmaygetc(void)
+void
+immc_romputc(char c)
 {
-       return -1;
+       immc_cnputc (0, c);
 }
 
 #endif /* ENABLE_IMMEDIATE_CONSOLE */
diff --git a/i386/i386at/kd.c b/i386/i386at/kd.c
index bbb0023..5656e83 100644
--- a/i386/i386at/kd.c
+++ b/i386/i386at/kd.c
@@ -1162,7 +1162,7 @@ kdinit(void)
        kd_senddata(k_comm);
        kd_initialized = TRUE;
 
-#ifdef ENABLE_IMMEDIATE_CONSOLE
+#if    ENABLE_IMMEDIATE_CONSOLE
        /* Now that we're set up, we no longer need or want the
            immediate console.  */
        {
diff --git a/i386/i386at/kd.h b/i386/i386at/kd.h
index 4ac93c7..0cfed69 100644
--- a/i386/i386at/kd.h
+++ b/i386/i386at/kd.h
@@ -740,6 +740,7 @@ extern int kdcninit(struct consdev *cp);
 extern int kdcngetc(dev_t dev, int wait);
 extern int kdcnmaygetc (void);
 extern int kdcnputc(dev_t dev, int c);
+extern void kd_setpos(csrpos_t newpos);
 
 extern void kd_slmwd (void *start, int count, int value);
 extern void kd_slmscu (void *from, void *to, int count);
diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c
index bc34c9b..fdf983b 100644
--- a/i386/i386at/model_dep.c
+++ b/i386/i386at/model_dep.c
@@ -77,6 +77,10 @@
 #include <xen/xen.h>
 #endif /* MACH_XEN */
 
+#if    ENABLE_IMMEDIATE_CONSOLE
+#include "immc.h"
+#endif /* ENABLE_IMMEDIATE_CONSOLE */
+
 /* Location of the kernel's symbol table.
    Both of these are 0 if none is available.  */
 #if MACH_KDB
@@ -137,6 +141,7 @@ static vm_size_t avail_remaining;
 
 extern char    version[];
 
+/* If set, reboot the system on ctrl-alt-delete.  */
 boolean_t      rebootflag = FALSE;     /* exported to kdintr */
 
 /* XX interrupt stack pointer and highwater mark, for locore.S.  */
@@ -540,6 +545,10 @@ i386at_init(void)
  */
 void c_boot_entry(vm_offset_t bi)
 {
+#if    ENABLE_IMMEDIATE_CONSOLE
+       romputc = immc_romputc;
+#endif /* ENABLE_IMMEDIATE_CONSOLE */
+
        /* Stash the boot_image_info pointer.  */
        boot_info = *(typeof(boot_info)*)phystokv(bi);
        int cpu_type;
diff --git a/i386/i386at/rtc.c b/i386/i386at/rtc.c
index 946f08f..01e0977 100644
--- a/i386/i386at/rtc.c
+++ b/i386/i386at/rtc.c
@@ -66,8 +66,9 @@ rtcinit(void)
 
 
 int
-rtcget(unsigned char *regs)
+rtcget(struct rtc_st *st)
 {
+       unsigned char *regs = (unsigned char *)st;
        if (first_rtcopen_ever) {
                rtcinit();
                first_rtcopen_ever = FALSE;
@@ -82,8 +83,9 @@ rtcget(unsigned char *regs)
 }
 
 void
-rtcput(unsigned char *regs)
+rtcput(struct rtc_st *st)
 {
+       unsigned char *regs = (unsigned char *)st;
        unsigned char   x;
 
        if (first_rtcopen_ever) {
diff --git a/i386/intel/read_fault.c b/i386/intel/read_fault.c
index 29f4439..4b1edce 100644
--- a/i386/intel/read_fault.c
+++ b/i386/intel/read_fault.c
@@ -31,7 +31,7 @@
 #include <vm/vm_page.h>
 #include <vm/pmap.h>
 
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 
 /*
  *     Expansion of vm_fault for read fault in kernel mode.
diff --git a/include/mach_debug/ipc_info.h b/include/mach_debug/ipc_info.h
index ef0b0c6..a47ae7b 100644
--- a/include/mach_debug/ipc_info.h
+++ b/include/mach_debug/ipc_info.h
@@ -43,40 +43,17 @@
  *     in mach_debug_types.defs when adding/removing fields.
  */
 
-
-typedef struct ipc_info_space {
-       natural_t iis_genno_mask;       /* generation number mask */
-       natural_t iis_table_size;       /* size of table */
-       natural_t iis_table_next;       /* next possible size of table */
-       natural_t iis_tree_size;        /* size of tree */
-       natural_t iis_tree_small;       /* # of small entries in tree */
-       natural_t iis_tree_hash;        /* # of hashed entries in tree */
-} ipc_info_space_t;
-
-
 typedef struct ipc_info_name {
        mach_port_t iin_name;           /* port name, including gen number */
-/*boolean_t*/integer_t iin_collision;  /* collision at this entry? */
-/*boolean_t*/integer_t iin_compat;     /* is this a compat-mode entry? */
 /*boolean_t*/integer_t iin_marequest;  /* extant msg-accepted request? */
        mach_port_type_t iin_type;      /* straight port type */
        mach_port_urefs_t iin_urefs;    /* user-references */
        vm_offset_t iin_object;         /* object pointer */
        natural_t iin_next;             /* marequest/next in free list */
-       natural_t iin_hash;             /* hash index */
 } ipc_info_name_t;
 
 typedef ipc_info_name_t *ipc_info_name_array_t;
 
-
-typedef struct ipc_info_tree_name {
-       ipc_info_name_t iitn_name;
-       mach_port_t iitn_lchild;        /* name of left child */
-       mach_port_t iitn_rchild;        /* name of right child */
-} ipc_info_tree_name_t;
-
-typedef ipc_info_tree_name_t *ipc_info_tree_name_array_t;
-
 /*
  *     Type definitions for mach_port_kernel_object.
  *     By remarkable coincidence, these closely resemble
diff --git a/include/mach_debug/mach_debug.defs 
b/include/mach_debug/mach_debug.defs
index fb6e3a9..c8e8b1b 100644
--- a/include/mach_debug/mach_debug.defs
+++ b/include/mach_debug/mach_debug.defs
@@ -57,14 +57,7 @@ routine      mach_port_get_srights(
                name            : mach_port_name_t;
        out     srights         : mach_port_rights_t);
 
-/*
- *     Returns information about the global reverse hash table.
- */
-
-routine host_ipc_hash_info(
-               host            : host_t;
-       out     info            : hash_info_bucket_array_t,
-                                       CountInOut, Dealloc);
+skip;  /* host_ipc_hash_info */
 
 /*
  *     Returns information about the marequest hash table.
@@ -76,17 +69,7 @@ routine host_ipc_marequest_info(
        out     info            : hash_info_bucket_array_t,
                                        CountInOut, Dealloc);
 
-/*
- *     Returns information about an IPC space.
- */
-
-routine mach_port_space_info(
-               task            : ipc_space_t;
-       out     info            : ipc_info_space_t;
-       out     table_info      : ipc_info_name_array_t,
-                                       CountInOut, Dealloc;
-       out     tree_info       : ipc_info_tree_name_array_t,
-                                       CountInOut, Dealloc);
+skip;  /* mach_port_space_info */
 
 /*
  *     Returns information about the dead-name requests
diff --git a/include/mach_debug/mach_debug_types.defs 
b/include/mach_debug/mach_debug_types.defs
index d24b6f9..8df2f34 100644
--- a/include/mach_debug/mach_debug_types.defs
+++ b/include/mach_debug/mach_debug_types.defs
@@ -38,14 +38,9 @@ type cache_info_array_t = array[] of cache_info_t;
 type hash_info_bucket_t = struct[1] of natural_t;
 type hash_info_bucket_array_t = array[] of hash_info_bucket_t;
 
-type ipc_info_space_t = struct[6] of natural_t;
-
-type ipc_info_name_t = struct[9] of natural_t;
+type ipc_info_name_t = struct[6] of natural_t;
 type ipc_info_name_array_t = array[] of ipc_info_name_t;
 
-type ipc_info_tree_name_t = struct[11] of natural_t;
-type ipc_info_tree_name_array_t = array[] of ipc_info_tree_name_t;
-
 type vm_region_info_t = struct[11] of natural_t;
 type vm_region_info_array_t = array[] of vm_region_info_t;
 
diff --git a/ipc/ipc_entry.c b/ipc/ipc_entry.c
index e78f74e..a5fe319 100644
--- a/ipc/ipc_entry.c
+++ b/ipc/ipc_entry.c
@@ -46,150 +46,10 @@
 #include <ipc/ipc_types.h>
 #include <ipc/ipc_entry.h>
 #include <ipc/ipc_space.h>
-#include <ipc/ipc_splay.h>
-#include <ipc/ipc_hash.h>
 #include <ipc/ipc_table.h>
 #include <ipc/ipc_object.h>
 
-struct kmem_cache ipc_tree_entry_cache;
-
-/*
- *     Routine:        ipc_entry_tree_collision
- *     Purpose:
- *             Checks if "name" collides with an allocated name
- *             in the space's tree.  That is, returns TRUE
- *             if the splay tree contains a name with the same
- *             index as "name".
- *     Conditions:
- *             The space is locked (read or write) and active.
- */
-
-boolean_t
-ipc_entry_tree_collision(
-       ipc_space_t     space,
-       mach_port_t     name)
-{
-       mach_port_index_t index;
-       mach_port_t lower, upper;
-
-       assert(space->is_active);
-
-       /*
-        *      Check if we collide with the next smaller name
-        *      or the next larger name.
-        */
-
-       ipc_splay_tree_bounds(&space->is_tree, name, &lower, &upper);
-
-       index = MACH_PORT_INDEX(name);
-       return (((lower != ~0) && (MACH_PORT_INDEX(lower) == index)) ||
-               ((upper != 0) && (MACH_PORT_INDEX(upper) == index)));
-}
-
-/*
- *     Routine:        ipc_entry_lookup
- *     Purpose:
- *             Searches for an entry, given its name.
- *     Conditions:
- *             The space must be read or write locked throughout.
- *             The space must be active.
- */
-
-ipc_entry_t
-ipc_entry_lookup(
-       ipc_space_t space,
-       mach_port_t name)
-{
-       mach_port_index_t index;
-       ipc_entry_t entry;
-
-       assert(space->is_active);
-
-       index = MACH_PORT_INDEX(name);
-       if (index < space->is_table_size) {
-               entry = &space->is_table[index];
-               if (IE_BITS_GEN(entry->ie_bits) != MACH_PORT_GEN(name))
-                       if (entry->ie_bits & IE_BITS_COLLISION) {
-                               assert(space->is_tree_total > 0);
-                               goto tree_lookup;
-                       } else
-                               entry = IE_NULL;
-               else if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
-                       entry = IE_NULL;
-       } else if (space->is_tree_total == 0)
-               entry = IE_NULL;
-       else
-           tree_lookup:
-               entry = (ipc_entry_t)
-                               ipc_splay_tree_lookup(&space->is_tree, name);
-
-       assert((entry == IE_NULL) || IE_BITS_TYPE(entry->ie_bits));
-       return entry;
-}
-
-/*
- *     Routine:        ipc_entry_get
- *     Purpose:
- *             Tries to allocate an entry out of the space.
- *     Conditions:
- *             The space is write-locked and active throughout.
- *             An object may be locked.  Will not allocate memory.
- *     Returns:
- *             KERN_SUCCESS            A free entry was found.
- *             KERN_NO_SPACE           No entry allocated.
- */
-
-kern_return_t
-ipc_entry_get(
-       ipc_space_t space,
-       mach_port_t *namep,
-       ipc_entry_t *entryp)
-{
-       ipc_entry_t table;
-       mach_port_index_t first_free;
-       mach_port_t new_name;
-       ipc_entry_t free_entry;
-
-       assert(space->is_active);
-
-       table = space->is_table;
-       first_free = table->ie_next;
-
-       if (first_free == 0)
-               return KERN_NO_SPACE;
-
-       free_entry = &table[first_free];
-       table->ie_next = free_entry->ie_next;
-
-       /*
-        *      Initialize the new entry.  We need only
-        *      increment the generation number and clear ie_request.
-        */
-
-    {
-       mach_port_gen_t gen;
-
-       assert((free_entry->ie_bits &~ IE_BITS_GEN_MASK) == 0);
-       gen = free_entry->ie_bits + IE_BITS_GEN_ONE;
-       free_entry->ie_bits = gen;
-       free_entry->ie_request = 0;
-       new_name = MACH_PORT_MAKE(first_free, gen);
-    }
-
-       /*
-        *      The new name can't be MACH_PORT_NULL because index
-        *      is non-zero.  It can't be MACH_PORT_DEAD because
-        *      the table isn't allowed to grow big enough.
-        *      (See comment in ipc/ipc_table.h.)
-        */
-
-       assert(MACH_PORT_VALID(new_name));
-       assert(free_entry->ie_object == IO_NULL);
-
-       *namep = new_name;
-       *entryp = free_entry;
-       return KERN_SUCCESS;
-}
+struct kmem_cache ipc_entry_cache;
 
 /*
  *     Routine:        ipc_entry_alloc
@@ -212,23 +72,44 @@ ipc_entry_alloc(
        ipc_entry_t     *entryp)
 {
        kern_return_t kr;
+       ipc_entry_t entry;
+       rdxtree_key_t key;
 
        is_write_lock(space);
 
-       for (;;) {
-               if (!space->is_active) {
-                       is_write_unlock(space);
-                       return KERN_INVALID_TASK;
-               }
+       if (!space->is_active) {
+               is_write_unlock(space);
+               return KERN_INVALID_TASK;
+       }
 
-               kr = ipc_entry_get(space, namep, entryp);
-               if (kr == KERN_SUCCESS)
-                       return kr;
+       kr = ipc_entry_get(space, namep, entryp);
+       if (kr == KERN_SUCCESS)
+               /* Success.  Space is write-locked.  */
+               return kr;
 
-               kr = ipc_entry_grow_table(space);
-               if (kr != KERN_SUCCESS)
-                       return kr; /* space is unlocked */
+       entry = ie_alloc();
+       if (entry == IE_NULL) {
+               is_write_unlock(space);
+               return KERN_RESOURCE_SHORTAGE;
        }
+
+       kr = rdxtree_insert_alloc(&space->is_map, entry, &key);
+       if (kr) {
+               is_write_unlock(space);
+               ie_free(entry);
+               return kr;
+       }
+       space->is_size += 1;
+
+       entry->ie_bits = 0;
+       entry->ie_object = IO_NULL;
+       entry->ie_request = 0;
+       entry->ie_name = (mach_port_t) key;
+
+       *entryp = entry;
+       *namep = (mach_port_t) key;
+       /* Success.  Space is write-locked.  */
+       return KERN_SUCCESS;
 }
 
 /*
@@ -252,586 +133,79 @@ ipc_entry_alloc_name(
        mach_port_t     name,
        ipc_entry_t     *entryp)
 {
-       mach_port_index_t index = MACH_PORT_INDEX(name);
-       mach_port_gen_t gen = MACH_PORT_GEN(name);
-       ipc_tree_entry_t tree_entry = ITE_NULL;
-
+       kern_return_t kr;
+       ipc_entry_t entry, e, *prevp;
+       void **slot;
        assert(MACH_PORT_VALID(name));
 
-
        is_write_lock(space);
 
-       for (;;) {
-               ipc_entry_t entry;
-               ipc_tree_entry_t tentry;
-               ipc_table_size_t its;
-
-               if (!space->is_active) {
-                       is_write_unlock(space);
-                       if (tree_entry) ite_free(tree_entry);
-                       return KERN_INVALID_TASK;
-               }
-
-               /*
-                *      If we are under the table cutoff,
-                *      there are three cases:
-                *              1) The entry is inuse, for the same name
-                *              2) The entry is inuse, for a different name
-                *              3) The entry is free
-                */
-
-               if ((0 < index) && (index < space->is_table_size)) {
-                       ipc_entry_t table = space->is_table;
-
-                       entry = &table[index];
-
-                       if (IE_BITS_TYPE(entry->ie_bits)) {
-                               if (IE_BITS_GEN(entry->ie_bits) == gen) {
-                                       *entryp = entry;
-                                       if (tree_entry) ite_free(tree_entry);
-                                       return KERN_SUCCESS;
-                               }
-                       } else {
-                               mach_port_index_t free_index, next_index;
-
-                               /*
-                                *      Rip the entry out of the free list.
-                                */
-
-                               for (free_index = 0;
-                                    (next_index = table[free_index].ie_next)
-                                                       != index;
-                                    free_index = next_index)
-                                       continue;
-
-                               table[free_index].ie_next =
-                                       table[next_index].ie_next;
-
-                               entry->ie_bits = gen;
-                               assert(entry->ie_object == IO_NULL);
-                               entry->ie_request = 0;
-
-                               *entryp = entry;
-                               if (tree_entry) ite_free(tree_entry);
-                               return KERN_SUCCESS;
-                       }
-               }
-
-               /*
-                *      Before trying to allocate any memory,
-                *      check if the entry already exists in the tree.
-                *      This avoids spurious resource errors.
-                *      The splay tree makes a subsequent lookup/insert
-                *      of the same name cheap, so this costs little.
-                */
-
-               if ((space->is_tree_total > 0) &&
-                   ((tentry = ipc_splay_tree_lookup(&space->is_tree, name))
-                                                       != ITE_NULL)) {
-                       assert(tentry->ite_space == space);
-                       assert(IE_BITS_TYPE(tentry->ite_bits));
-
-                       *entryp = &tentry->ite_entry;
-                       if (tree_entry) ite_free(tree_entry);
-                       return KERN_SUCCESS;
-               }
-
-               its = space->is_table_next;
-
-               /*
-                *      Check if the table should be grown.
-                *
-                *      Note that if space->is_table_size == its->its_size,
-                *      then we won't ever try to grow the table.
-                *
-                *      Note that we are optimistically assuming that name
-                *      doesn't collide with any existing names.  (So if
-                *      it were entered into the tree, is_tree_small would
-                *      be incremented.)  This is OK, because even in that
-                *      case, we don't lose memory by growing the table.
-                */
-
-               if ((space->is_table_size <= index) &&
-                   (index < its->its_size) &&
-                   (((its->its_size - space->is_table_size) *
-                     sizeof(struct ipc_entry)) <
-                    ((space->is_tree_small + 1) *
-                     sizeof(struct ipc_tree_entry)))) {
-                       kern_return_t kr;
-
-                       /*
-                        *      Can save space by growing the table.
-                        *      Because the space will be unlocked,
-                        *      we must restart.
-                        */
-
-                       kr = ipc_entry_grow_table(space);
-                       assert(kr != KERN_NO_SPACE);
-                       if (kr != KERN_SUCCESS) {
-                               /* space is unlocked */
-                               if (tree_entry) ite_free(tree_entry);
-                               return kr;
-                       }
-
-                       continue;
-               }
-
-               /*
-                *      If a splay-tree entry was allocated previously,
-                *      go ahead and insert it into the tree.
-                */
-
-               if (tree_entry != ITE_NULL) {
-                       space->is_tree_total++;
-
-                       if (index < space->is_table_size)
-                               space->is_table[index].ie_bits |=
-                                       IE_BITS_COLLISION;
-                       else if ((index < its->its_size) &&
-                                !ipc_entry_tree_collision(space, name))
-                               space->is_tree_small++;
-
-                       ipc_splay_tree_insert(&space->is_tree,
-                                             name, tree_entry);
-
-                       tree_entry->ite_bits = 0;
-                       tree_entry->ite_object = IO_NULL;
-                       tree_entry->ite_request = 0;
-                       tree_entry->ite_space = space;
-                       *entryp = &tree_entry->ite_entry;
-                       return KERN_SUCCESS;
-               }
-
-               /*
-                *      Allocate a tree entry and try again.
-                */
-
+       if (!space->is_active) {
                is_write_unlock(space);
-               tree_entry = ite_alloc();
-               if (tree_entry == ITE_NULL)
-                       return KERN_RESOURCE_SHORTAGE;
-               is_write_lock(space);
-       }
-}
-
-/*
- *     Routine:        ipc_entry_dealloc
- *     Purpose:
- *             Deallocates an entry from a space.
- *     Conditions:
- *             The space must be write-locked throughout.
- *             The space must be active.
- */
-
-void
-ipc_entry_dealloc(
-       ipc_space_t     space,
-       mach_port_t     name,
-       ipc_entry_t     entry)
-{
-       ipc_entry_t table;
-       ipc_entry_num_t size;
-       mach_port_index_t index;
-
-       assert(space->is_active);
-       assert(entry->ie_object == IO_NULL);
-       assert(entry->ie_request == 0);
-
-       index = MACH_PORT_INDEX(name);
-       table = space->is_table;
-       size = space->is_table_size;
-
-       if ((index < size) && (entry == &table[index])) {
-               assert(IE_BITS_GEN(entry->ie_bits) == MACH_PORT_GEN(name));
-
-               if (entry->ie_bits & IE_BITS_COLLISION) {
-                       struct ipc_splay_tree small, collisions;
-                       ipc_tree_entry_t tentry;
-                       mach_port_t tname;
-                       boolean_t pick;
-                       ipc_entry_bits_t bits;
-                       ipc_object_t obj;
-
-                       /* must move an entry from tree to table */
-
-                       ipc_splay_tree_split(&space->is_tree,
-                                            MACH_PORT_MAKE(index+1, 0),
-                                            &collisions);
-                       ipc_splay_tree_split(&collisions,
-                                            MACH_PORT_MAKE(index, 0),
-                                            &small);
-
-                       pick = ipc_splay_tree_pick(&collisions,
-                                                  &tname, &tentry);
-                       assert(pick);
-                       assert(MACH_PORT_INDEX(tname) == index);
-
-                       bits = tentry->ite_bits;
-                       entry->ie_bits = bits | MACH_PORT_GEN(tname);
-                       entry->ie_object = obj = tentry->ite_object;
-                       entry->ie_request = tentry->ite_request;
-                       assert(tentry->ite_space == space);
-
-                       if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND) {
-                               ipc_hash_global_delete(space, obj,
-                                                      tname, tentry);
-                               ipc_hash_local_insert(space, obj,
-                                                     index, entry);
-                       }
-
-                       ipc_splay_tree_delete(&collisions, tname, tentry);
-
-                       assert(space->is_tree_total > 0);
-                       space->is_tree_total--;
-
-                       /* check if collision bit should still be on */
-
-                       pick = ipc_splay_tree_pick(&collisions,
-                                                  &tname, &tentry);
-                       if (pick) {
-                               entry->ie_bits |= IE_BITS_COLLISION;
-                               ipc_splay_tree_join(&space->is_tree,
-                                                   &collisions);
-                       }
-
-                       ipc_splay_tree_join(&space->is_tree, &small);
-               } else {
-                       entry->ie_bits &= IE_BITS_GEN_MASK;
-                       entry->ie_next = table->ie_next;
-                       table->ie_next = index;
-               }
-       } else {
-               ipc_tree_entry_t tentry = (ipc_tree_entry_t) entry;
-
-               assert(tentry->ite_space == space);
-
-               ipc_splay_tree_delete(&space->is_tree, name, tentry);
-
-               assert(space->is_tree_total > 0);
-               space->is_tree_total--;
-
-               if (index < size) {
-                       ipc_entry_t ientry = &table[index];
-
-                       assert(ientry->ie_bits & IE_BITS_COLLISION);
-
-                       if (!ipc_entry_tree_collision(space, name))
-                               ientry->ie_bits &= ~IE_BITS_COLLISION;
-               } else if ((index < space->is_table_next->its_size) &&
-                          !ipc_entry_tree_collision(space, name)) {
-                       assert(space->is_tree_small > 0);
-                       space->is_tree_small--;
-               }
+               return KERN_INVALID_TASK;
        }
-}
-
-/*
- *     Routine:        ipc_entry_grow_table
- *     Purpose:
- *             Grows the table in a space.
- *     Conditions:
- *             The space must be write-locked and active before.
- *             If successful, it is also returned locked.
- *             Allocates memory.
- *     Returns:
- *             KERN_SUCCESS            Grew the table.
- *             KERN_SUCCESS            Somebody else grew the table.
- *             KERN_SUCCESS            The space died.
- *             KERN_NO_SPACE           Table has maximum size already.
- *             KERN_RESOURCE_SHORTAGE  Couldn't allocate a new table.
- */
-
-kern_return_t
-ipc_entry_grow_table(ipc_space_t space)
-{
-       ipc_entry_num_t osize, size, nsize;
 
-       do {
-               ipc_entry_t otable, table;
-               ipc_table_size_t oits, its, nits;
-               mach_port_index_t i, free_index;
+       slot = rdxtree_lookup_slot(&space->is_map, (rdxtree_key_t) name);
+       if (slot != NULL)
+               entry = *(ipc_entry_t *) slot;
 
-               assert(space->is_active);
-
-               if (space->is_growing) {
-                       /*
-                        *      Somebody else is growing the table.
-                        *      We just wait for them to finish.
-                        */
-
-                       assert_wait((event_t) space, FALSE);
+       if (slot == NULL || entry == IE_NULL) {
+               entry = ie_alloc();
+               if (entry == IE_NULL) {
                        is_write_unlock(space);
-                       thread_block((void (*)()) 0);
-                       is_write_lock(space);
-                       return KERN_SUCCESS;
-               }
-
-               otable = space->is_table;
-               its = space->is_table_next;
-               size = its->its_size;
-               oits = its - 1;
-               osize = oits->its_size;
-               nits = its + 1;
-               nsize = nits->its_size;
-
-               if (osize == size) {
-                       is_write_unlock(space);
-                       printf_once("no more room for ipc_entry_grow_table in 
space %p\n", space);
-                       return KERN_NO_SPACE;
-               }
-
-               assert((osize < size) && (size <= nsize));
-
-               /*
-                *      OK, we'll attempt to grow the table.
-                *      The realloc requires that the old table
-                *      remain in existence.
-                */
-
-               space->is_growing = TRUE;
-               is_write_unlock(space);
-               if (it_entries_reallocable(oits))
-                       table = it_entries_realloc(oits, otable, its);
-               else
-                       table = it_entries_alloc(its);
-               is_write_lock(space);
-               space->is_growing = FALSE;
-
-               /*
-                *      We need to do a wakeup on the space,
-                *      to rouse waiting threads.  We defer
-                *      this until the space is unlocked,
-                *      because we don't want them to spin.
-                */
-
-               if (table == IE_NULL) {
-                       is_write_unlock(space);
-                       thread_wakeup((event_t) space);
                        return KERN_RESOURCE_SHORTAGE;
                }
 
-               if (!space->is_active) {
-                       /*
-                        *      The space died while it was unlocked.
-                        */
-
-                       is_write_unlock(space);
-                       thread_wakeup((event_t) space);
-                       it_entries_free(its, table);
-                       is_write_lock(space);
-                       return KERN_SUCCESS;
-               }
-
-               assert(space->is_table == otable);
-               assert(space->is_table_next == its);
-               assert(space->is_table_size == osize);
-
-               space->is_table = table;
-               space->is_table_size = size;
-               space->is_table_next = nits;
-
-               /*
-                *      If we did a realloc, it remapped the data.
-                *      Otherwise we copy by hand first.  Then we have
-                *      to clear the index fields in the old part and
-                *      zero the new part.
-                */
-
-               if (!it_entries_reallocable(oits))
-                       memcpy(table, otable,
-                             osize * sizeof(struct ipc_entry));
-
-               for (i = 0; i < osize; i++)
-                       table[i].ie_index = 0;
-
-               (void) memset((void *) (table + osize), 0,
-                     (size - osize) * sizeof(struct ipc_entry));
-
-               /*
-                *      Put old entries into the reverse hash table.
-                */
-
-               for (i = 0; i < osize; i++) {
-                       ipc_entry_t entry = &table[i];
-
-                       if (IE_BITS_TYPE(entry->ie_bits) ==
-                                               MACH_PORT_TYPE_SEND)
-                               ipc_hash_local_insert(space, entry->ie_object,
-                                                     i, entry);
-               }
-
-               /*
-                *      If there are entries in the splay tree,
-                *      then we have work to do:
-                *              1) transfer entries to the table
-                *              2) update is_tree_small
-                */
-
-               if (space->is_tree_total > 0) {
-                       mach_port_index_t index;
-                       boolean_t delete;
-                       struct ipc_splay_tree ignore;
-                       struct ipc_splay_tree move;
-                       struct ipc_splay_tree small;
-                       ipc_entry_num_t nosmall;
-                       ipc_tree_entry_t tentry;
-
-                       /*
-                        *      The splay tree divides into four regions,
-                        *      based on the index of the entries:
-                        *              1) 0 <= index < osize
-                        *              2) osize <= index < size
-                        *              3) size <= index < nsize
-                        *              4) nsize <= index
-                        *
-                        *      Entries in the first part are ignored.
-                        *      Entries in the second part, that don't
-                        *      collide, are moved into the table.
-                        *      Entries in the third part, that don't
-                        *      collide, are counted for is_tree_small.
-                        *      Entries in the fourth part are ignored.
-                        */
-
-                       ipc_splay_tree_split(&space->is_tree,
-                                            MACH_PORT_MAKE(nsize, 0),
-                                            &small);
-                       ipc_splay_tree_split(&small,
-                                            MACH_PORT_MAKE(size, 0),
-                                            &move);
-                       ipc_splay_tree_split(&move,
-                                            MACH_PORT_MAKE(osize, 0),
-                                            &ignore);
-
-                       /* move entries into the table */
-
-                       for (tentry = ipc_splay_traverse_start(&move);
-                            tentry != ITE_NULL;
-                            tentry = ipc_splay_traverse_next(&move, delete)) {
-                               mach_port_t name;
-                               mach_port_gen_t gen;
-                               mach_port_type_t type;
-                               ipc_entry_bits_t bits;
-                               ipc_object_t obj;
-                               ipc_entry_t entry;
-
-                               name = tentry->ite_name;
-                               gen = MACH_PORT_GEN(name);
-                               index = MACH_PORT_INDEX(name);
-
-                               assert(tentry->ite_space == space);
-                               assert((osize <= index) && (index < size));
+               entry->ie_bits = 0;
+               entry->ie_object = IO_NULL;
+               entry->ie_request = 0;
+               entry->ie_name = name;
 
-                               entry = &table[index];
-
-                               /* collision with previously moved entry? */
-
-                               bits = entry->ie_bits;
-                               if (bits != 0) {
-                                       assert(IE_BITS_TYPE(bits));
-                                       assert(IE_BITS_GEN(bits) != gen);
-
-                                       entry->ie_bits =
-                                               bits | IE_BITS_COLLISION;
-                                       delete = FALSE;
-                                       continue;
-                               }
-
-                               bits = tentry->ite_bits;
-                               type = IE_BITS_TYPE(bits);
-                               assert(type != MACH_PORT_TYPE_NONE);
-
-                               entry->ie_bits = bits | gen;
-                               entry->ie_object = obj = tentry->ite_object;
-                               entry->ie_request = tentry->ite_request;
-
-                               if (type == MACH_PORT_TYPE_SEND) {
-                                       ipc_hash_global_delete(space, obj,
-                                                              name, tentry);
-                                       ipc_hash_local_insert(space, obj,
-                                                             index, entry);
-                               }
-
-                               space->is_tree_total--;
-                               delete = TRUE;
-                       }
-                       ipc_splay_traverse_finish(&move);
-
-                       /* count entries for is_tree_small */
-
-                       nosmall = 0; index = 0;
-                       for (tentry = ipc_splay_traverse_start(&small);
-                            tentry != ITE_NULL;
-                            tentry = ipc_splay_traverse_next(&small, FALSE)) {
-                               mach_port_index_t nindex;
-
-                               nindex = MACH_PORT_INDEX(tentry->ite_name);
-
-                               if (nindex != index) {
-                                       nosmall++;
-                                       index = nindex;
-                               }
+               if (slot != NULL)
+                       rdxtree_replace_slot(slot, entry);
+               else {
+                       kr = rdxtree_insert(&space->is_map,
+                                           (rdxtree_key_t) name, entry);
+                       if (kr != KERN_SUCCESS) {
+                               is_write_unlock(space);
+                               ie_free(entry);
+                               return kr;
                        }
-                       ipc_splay_traverse_finish(&small);
-
-                       assert(nosmall <= (nsize - size));
-                       assert(nosmall <= space->is_tree_total);
-                       space->is_tree_small = nosmall;
-
-                       /* put the splay tree back together */
-
-                       ipc_splay_tree_join(&space->is_tree, &small);
-                       ipc_splay_tree_join(&space->is_tree, &move);
-                       ipc_splay_tree_join(&space->is_tree, &ignore);
                }
+               space->is_size += 1;
 
-               /*
-                *      Add entries in the new part which still aren't used
-                *      to the free list.  Add them in reverse order,
-                *      and set the generation number to -1, so that
-                *      early allocations produce "natural" names.
-                */
-
-               free_index = table[0].ie_next;
-               for (i = size-1; i >= osize; --i) {
-                       ipc_entry_t entry = &table[i];
+               *entryp = entry;
+               /* Success.  Space is write-locked.  */
+               return KERN_SUCCESS;
+       }
 
-                       if (entry->ie_bits == 0) {
-                               entry->ie_bits = IE_BITS_GEN_MASK;
-                               entry->ie_next = free_index;
-                               free_index = i;
-                       }
-               }
-               table[0].ie_next = free_index;
+       if (IE_BITS_TYPE(entry->ie_bits)) {
+               /* Used entry.  */
+               *entryp = entry;
+               /* Success.  Space is write-locked.  */
+               return KERN_SUCCESS;
+       }
 
-               /*
-                *      Now we need to free the old table.
-                *      If the space dies or grows while unlocked,
-                *      then we can quit here.
-                */
+       /* Free entry.  Rip the entry out of the free list.  */
+       for (prevp = &space->is_free_list, e = space->is_free_list;
+            e != entry;
+            ({ prevp = &e->ie_next_free; e = e->ie_next_free; }))
+               continue;
 
-               is_write_unlock(space);
-               thread_wakeup((event_t) space);
-               it_entries_free(oits, otable);
-               is_write_lock(space);
-               if (!space->is_active || (space->is_table_next != nits))
-                       return KERN_SUCCESS;
+       *prevp = entry->ie_next_free;
+       space->is_free_list_size -= 1;
 
-               /*
-                *      We might have moved enough entries from
-                *      the splay tree into the table that
-                *      the table can be profitably grown again.
-                *
-                *      Note that if size == nsize, then
-                *      space->is_tree_small == 0.
-                */
-       } while ((space->is_tree_small > 0) &&
-                (((nsize - size) * sizeof(struct ipc_entry)) <
-                 (space->is_tree_small * sizeof(struct ipc_tree_entry))));
+       entry->ie_bits = 0;
+       assert(entry->ie_object == IO_NULL);
+       assert(entry->ie_name == name);
+       entry->ie_request = 0;
 
+       space->is_size += 1;
+       *entryp = entry;
+       /* Success.  Space is write-locked.  */
        return KERN_SUCCESS;
 }
 
-
 #if    MACH_KDB
 #include <ddb/db_output.h>
 #include <kern/task.h>
diff --git a/ipc/ipc_entry.h b/ipc/ipc_entry.h
index cb6d3f9..b429984 100644
--- a/ipc/ipc_entry.h
+++ b/ipc/ipc_entry.h
@@ -48,47 +48,27 @@
 
 /*
  *     Spaces hold capabilities for ipc_object_t's (ports and port sets).
- *     Each ipc_entry_t records a capability.  Most capabilities have
- *     small names, and the entries are elements of a table.
- *     Capabilities can have large names, and a splay tree holds
- *     those entries.  The cutoff point between the table and the tree
- *     is adjusted dynamically to minimize memory consumption.
- *
- *     The ie_index field of entries in the table implements
- *     a ordered hash table with open addressing and linear probing.
- *     This hash table converts (space, object) -> name.
- *     It is used independently of the other fields.
- *
- *     Free (unallocated) entries in the table have null ie_object
- *     fields.  The ie_bits field is zero except for IE_BITS_GEN.
- *     The ie_next (ie_request) field links free entries into a free list.
- *
- *     The first entry in the table (index 0) is always free.
- *     It is used as the head of the free list.
+ *     Each ipc_entry_t records a capability.
  */
 
 typedef unsigned int ipc_entry_bits_t;
 typedef ipc_table_elems_t ipc_entry_num_t;     /* number of entries */
 
 typedef struct ipc_entry {
+       mach_port_t ie_name;
        ipc_entry_bits_t ie_bits;
        struct ipc_object *ie_object;
        union {
-               mach_port_index_t next;
+               struct ipc_entry *next_free;
                /*XXX ipc_port_request_index_t request;*/
                unsigned int request;
        } index;
-       union {
-               mach_port_index_t table;
-               struct ipc_tree_entry *tree;
-       } hash;
 } *ipc_entry_t;
 
 #define        IE_NULL         ((ipc_entry_t) 0)
 
 #define        ie_request      index.request
-#define        ie_next         index.next
-#define        ie_index        hash.table
+#define        ie_next_free    index.next_free
 
 #define        IE_BITS_UREFS_MASK      0x0000ffff      /* 16 bits of 
user-reference */
 #define        IE_BITS_UREFS(bits)     ((bits) & IE_BITS_UREFS_MASK)
@@ -98,12 +78,10 @@ typedef struct ipc_entry {
 
 #define        IE_BITS_MAREQUEST       0x00200000      /* 1 bit for 
msg-accepted */
 
-#define        IE_BITS_COMPAT          0x00400000      /* 1 bit for 
compatibility */
-
-#define        IE_BITS_COLLISION       0x00800000      /* 1 bit for collisions 
*/
-#define        IE_BITS_RIGHT_MASK      0x007fffff      /* relevant to the 
right */
+#define        IE_BITS_RIGHT_MASK      0x003fffff      /* relevant to the 
right */
 
 #if PORT_GENERATIONS
+#error "not supported"
 #define        IE_BITS_GEN_MASK        0xff000000U     /* 8 bits for 
generation */
 #define        IE_BITS_GEN(bits)       ((bits) & IE_BITS_GEN_MASK)
 #define        IE_BITS_GEN_ONE         0x01000000      /* low bit of 
generation */
@@ -114,32 +92,9 @@ typedef struct ipc_entry {
 #endif
 
 
-typedef struct ipc_tree_entry {
-       struct ipc_entry ite_entry;
-       mach_port_t ite_name;
-       struct ipc_space *ite_space;
-       struct ipc_tree_entry *ite_lchild;
-       struct ipc_tree_entry *ite_rchild;
-} *ipc_tree_entry_t;
-
-#define        ITE_NULL        ((ipc_tree_entry_t) 0)
-
-#define        ite_bits        ite_entry.ie_bits
-#define        ite_object      ite_entry.ie_object
-#define        ite_request     ite_entry.ie_request
-#define        ite_next        ite_entry.hash.tree
-
-extern struct kmem_cache ipc_tree_entry_cache;
-
-#define ite_alloc()    ((ipc_tree_entry_t) 
kmem_cache_alloc(&ipc_tree_entry_cache))
-#define        ite_free(ite)   kmem_cache_free(&ipc_tree_entry_cache, 
(vm_offset_t) (ite))
-
-
-extern ipc_entry_t
-ipc_entry_lookup(ipc_space_t space, mach_port_t name);
-
-extern kern_return_t
-ipc_entry_get(ipc_space_t space, mach_port_t *namep, ipc_entry_t *entryp);
+extern struct kmem_cache ipc_entry_cache;
+#define ie_alloc()     ((ipc_entry_t) kmem_cache_alloc(&ipc_entry_cache))
+#define        ie_free(e)      kmem_cache_free(&ipc_entry_cache, (vm_offset_t) 
(e))
 
 extern kern_return_t
 ipc_entry_alloc(ipc_space_t space, mach_port_t *namep, ipc_entry_t *entryp);
@@ -147,12 +102,6 @@ ipc_entry_alloc(ipc_space_t space, mach_port_t *namep, 
ipc_entry_t *entryp);
 extern kern_return_t
 ipc_entry_alloc_name(ipc_space_t space, mach_port_t name, ipc_entry_t *entryp);
 
-extern void
-ipc_entry_dealloc(ipc_space_t space, mach_port_t name, ipc_entry_t entry);
-
-extern kern_return_t
-ipc_entry_grow_table(ipc_space_t space);
-
 ipc_entry_t
 db_ipc_object_by_name(
        task_t          task,
diff --git a/ipc/ipc_hash.c b/ipc/ipc_hash.c
deleted file mode 100644
index c2c6d6e..0000000
--- a/ipc/ipc_hash.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/* 
- * Mach Operating System
- * Copyright (c) 1991,1990,1989 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  address@hidden
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- * 
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- *     File:   ipc/ipc_hash.c
- *     Author: Rich Draves
- *     Date:   1989
- *
- *     Entry hash table operations.
- */
-
-#include <kern/printf.h>
-#include <mach/boolean.h>
-#include <mach/port.h>
-#include <kern/lock.h>
-#include <kern/kalloc.h>
-#include <ipc/port.h>
-#include <ipc/ipc_space.h>
-#include <ipc/ipc_object.h>
-#include <ipc/ipc_entry.h>
-#include <ipc/ipc_hash.h>
-#include <ipc/ipc_init.h>
-#include <ipc/ipc_types.h>
-
-#if    MACH_IPC_DEBUG
-#include <mach/kern_return.h>
-#include <mach_debug/hash_info.h>
-#include <vm/vm_map.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_user.h>
-#endif
-
-
-
-/*
- *     Routine:        ipc_hash_lookup
- *     Purpose:
- *             Converts (space, obj) -> (name, entry).
- *             Returns TRUE if an entry was found.
- *     Conditions:
- *             The space must be locked (read or write) throughout.
- */
-
-boolean_t
-ipc_hash_lookup(
-       ipc_space_t space,
-       ipc_object_t obj,
-       mach_port_t *namep,
-       ipc_entry_t *entryp)
-{
-       return (ipc_hash_local_lookup(space, obj, namep, entryp) ||
-               ((space->is_tree_hash > 0) &&
-                ipc_hash_global_lookup(space, obj, namep,
-                                       (ipc_tree_entry_t *) entryp)));
-}
-
-/*
- *     Routine:        ipc_hash_insert
- *     Purpose:
- *             Inserts an entry into the appropriate reverse hash table,
- *             so that ipc_hash_lookup will find it.
- *     Conditions:
- *             The space must be write-locked.
- */
-
-void
-ipc_hash_insert(
-       ipc_space_t     space,
-       ipc_object_t    obj,
-       mach_port_t     name,
-       ipc_entry_t     entry)
-{
-       mach_port_index_t index;
-
-       index = MACH_PORT_INDEX(name);
-       if ((index < space->is_table_size) &&
-           (entry == &space->is_table[index]))
-               ipc_hash_local_insert(space, obj, index, entry);
-       else
-               ipc_hash_global_insert(space, obj, name,
-                                      (ipc_tree_entry_t) entry);
-}
-
-/*
- *     Routine:        ipc_hash_delete
- *     Purpose:
- *             Deletes an entry from the appropriate reverse hash table.
- *     Conditions:
- *             The space must be write-locked.
- */
-
-void
-ipc_hash_delete(
-       ipc_space_t     space,
-       ipc_object_t    obj,
-       mach_port_t     name,
-       ipc_entry_t     entry)
-{
-       mach_port_index_t index;
-
-       index = MACH_PORT_INDEX(name);
-       if ((index < space->is_table_size) &&
-           (entry == &space->is_table[index]))
-               ipc_hash_local_delete(space, obj, index, entry);
-       else
-               ipc_hash_global_delete(space, obj, name,
-                                      (ipc_tree_entry_t) entry);
-}
-
-/*
- *     The global reverse hash table holds splay tree entries.
- *     It is a simple open-chaining hash table with singly-linked buckets.
- *     Each bucket is locked separately, with an exclusive lock.
- *     Within each bucket, move-to-front is used.
- */
-
-ipc_hash_index_t ipc_hash_global_size;
-ipc_hash_index_t ipc_hash_global_mask;
-
-#define IH_GLOBAL_HASH(space, obj)                                     \
-       (((((ipc_hash_index_t) ((vm_offset_t)space)) >> 4) +            \
-         (((ipc_hash_index_t) ((vm_offset_t)obj)) >> 6)) &             \
-        ipc_hash_global_mask)
-
-typedef struct ipc_hash_global_bucket {
-       decl_simple_lock_data(, ihgb_lock_data)
-       ipc_tree_entry_t ihgb_head;
-} *ipc_hash_global_bucket_t;
-
-#define        IHGB_NULL       ((ipc_hash_global_bucket_t) 0)
-
-#define        ihgb_lock_init(ihgb)    
simple_lock_init(&(ihgb)->ihgb_lock_data)
-#define        ihgb_lock(ihgb)         simple_lock(&(ihgb)->ihgb_lock_data)
-#define        ihgb_unlock(ihgb)       simple_unlock(&(ihgb)->ihgb_lock_data)
-
-ipc_hash_global_bucket_t ipc_hash_global_table;
-
-/*
- *     Routine:        ipc_hash_global_lookup
- *     Purpose:
- *             Converts (space, obj) -> (name, entry).
- *             Looks in the global table, for splay tree entries.
- *             Returns TRUE if an entry was found.
- *     Conditions:
- *             The space must be locked (read or write) throughout.
- */
-
-boolean_t
-ipc_hash_global_lookup(
-       ipc_space_t             space,
-       ipc_object_t            obj,
-       mach_port_t             *namep,
-       ipc_tree_entry_t        *entryp)
-{
-       ipc_hash_global_bucket_t bucket;
-       ipc_tree_entry_t this, *last;
-
-       assert(space != IS_NULL);
-       assert(obj != IO_NULL);
-
-       bucket = &ipc_hash_global_table[IH_GLOBAL_HASH(space, obj)];
-       ihgb_lock(bucket);
-
-       if ((this = bucket->ihgb_head) != ITE_NULL) {
-               if ((this->ite_object == obj) &&
-                   (this->ite_space == space)) {
-                       /* found it at front; no need to move */
-
-                       *namep = this->ite_name;
-                       *entryp = this;
-               } else for (last = &this->ite_next;
-                           (this = *last) != ITE_NULL;
-                           last = &this->ite_next) {
-                       if ((this->ite_object == obj) &&
-                           (this->ite_space == space)) {
-                               /* found it; move to front */
-
-                               *last = this->ite_next;
-                               this->ite_next = bucket->ihgb_head;
-                               bucket->ihgb_head = this;
-
-                               *namep = this->ite_name;
-                               *entryp = this;
-                               break;
-                       }
-               }
-       }
-
-       ihgb_unlock(bucket);
-       return this != ITE_NULL;
-}
-
-/*
- *     Routine:        ipc_hash_global_insert
- *     Purpose:
- *             Inserts an entry into the global reverse hash table.
- *     Conditions:
- *             The space must be write-locked.
- */
-
-void
-ipc_hash_global_insert(
-       ipc_space_t             space,
-       ipc_object_t            obj,
-       mach_port_t             name,
-       ipc_tree_entry_t        entry)
-{
-       ipc_hash_global_bucket_t bucket;
-
-
-       assert(entry->ite_name == name);
-       assert(space != IS_NULL);
-       assert(entry->ite_space == space);
-       assert(obj != IO_NULL);
-       assert(entry->ite_object == obj);
-
-       space->is_tree_hash++;
-       assert(space->is_tree_hash <= space->is_tree_total);
-
-       bucket = &ipc_hash_global_table[IH_GLOBAL_HASH(space, obj)];
-       ihgb_lock(bucket);
-
-       /* insert at front of bucket */
-
-       entry->ite_next = bucket->ihgb_head;
-       bucket->ihgb_head = entry;
-
-       ihgb_unlock(bucket);
-}
-
-/*
- *     Routine:        ipc_hash_global_delete
- *     Purpose:
- *             Deletes an entry from the global reverse hash table.
- *     Conditions:
- *             The space must be write-locked.
- */
-
-void
-ipc_hash_global_delete(
-       ipc_space_t             space,
-       ipc_object_t            obj,
-       mach_port_t             name,
-       ipc_tree_entry_t        entry)
-{
-       ipc_hash_global_bucket_t bucket;
-       ipc_tree_entry_t this, *last;
-
-       assert(entry->ite_name == name);
-       assert(space != IS_NULL);
-       assert(entry->ite_space == space);
-       assert(obj != IO_NULL);
-       assert(entry->ite_object == obj);
-
-       assert(space->is_tree_hash > 0);
-       space->is_tree_hash--;
-
-       bucket = &ipc_hash_global_table[IH_GLOBAL_HASH(space, obj)];
-       ihgb_lock(bucket);
-
-       for (last = &bucket->ihgb_head;
-            (this = *last) != ITE_NULL;
-            last = &this->ite_next) {
-               if (this == entry) {
-                       /* found it; remove from bucket */
-
-                       *last = this->ite_next;
-                       break;
-               }
-       }
-       assert(this != ITE_NULL);
-
-       ihgb_unlock(bucket);
-}
-
-/*
- *     Each space has a local reverse hash table, which holds
- *     entries from the space's table.  In fact, the hash table
- *     just uses a field (ie_index) in the table itself.
- *
- *     The local hash table is an open-addressing hash table,
- *     which means that when a collision occurs, instead of
- *     throwing the entry into a bucket, the entry is rehashed
- *     to another position in the table.  In this case the rehash
- *     is very simple: linear probing (ie, just increment the position).
- *     This simple rehash makes deletions tractable (they're still a pain),
- *     but it means that collisions tend to build up into clumps.
- *
- *     Because at least one entry in the table (index 0) is always unused,
- *     there will always be room in the reverse hash table.  If a table
- *     with n slots gets completely full, the reverse hash table will
- *     have one giant clump of n-1 slots and one free slot somewhere.
- *     Because entries are only entered into the reverse table if they
- *     are pure send rights (not receive, send-once, port-set,
- *     or dead-name rights), and free entries of course aren't entered,
- *     I expect the reverse hash table won't get unreasonably full.
- *
- *     Ordered hash tables (Amble & Knuth, Computer Journal, v. 17, no. 2,
- *     pp. 135-142.) may be desirable here.  They can dramatically help
- *     unsuccessful lookups.  But unsuccessful lookups are almost always
- *     followed by insertions, and those slow down somewhat.  They
- *     also can help deletions somewhat.  Successful lookups aren't affected.
- *     So possibly a small win; probably nothing significant.
- */
-
-#define        IH_LOCAL_HASH(obj, size)                                \
-       ((((mach_port_index_t) (vm_offset_t) (obj)) >> 6) & (size - 1))
-
-/*
- *     Routine:        ipc_hash_local_lookup
- *     Purpose:
- *             Converts (space, obj) -> (name, entry).
- *             Looks in the space's local table, for table entries.
- *             Returns TRUE if an entry was found.
- *     Conditions:
- *             The space must be locked (read or write) throughout.
- */
-
-boolean_t
-ipc_hash_local_lookup(
-       ipc_space_t     space,
-       ipc_object_t    obj,
-       mach_port_t     *namep,
-       ipc_entry_t     *entryp)
-{
-       ipc_entry_t table;
-       ipc_entry_num_t size;
-       mach_port_index_t hindex, index;
-
-       assert(space != IS_NULL);
-       assert(obj != IO_NULL);
-
-       table = space->is_table;
-       size = space->is_table_size;
-       hindex = IH_LOCAL_HASH(obj, size);
-
-       /*
-        *      Ideally, table[hindex].ie_index is the name we want.
-        *      However, must check ie_object to verify this,
-        *      because collisions can happen.  In case of a collision,
-        *      search farther along in the clump.
-        */
-
-       while ((index = table[hindex].ie_index) != 0) {
-               ipc_entry_t entry = &table[index];
-
-               if (entry->ie_object == obj) {
-                       *namep = MACH_PORT_MAKEB(index, entry->ie_bits);
-                       *entryp = entry;
-                       return TRUE;
-               }
-
-               if (++hindex == size)
-                       hindex = 0;
-       }
-
-       return FALSE;
-}
-
-/*
- *     Routine:        ipc_hash_local_insert
- *     Purpose:
- *             Inserts an entry into the space's reverse hash table.
- *     Conditions:
- *             The space must be write-locked.
- */
-
-void
-ipc_hash_local_insert(
-       ipc_space_t             space,
-       ipc_object_t            obj,
-       mach_port_index_t       index,
-       ipc_entry_t             entry)
-{
-       ipc_entry_t table;
-       ipc_entry_num_t size;
-       mach_port_index_t hindex;
-
-       assert(index != 0);
-       assert(space != IS_NULL);
-       assert(obj != IO_NULL);
-
-       table = space->is_table;
-       size = space->is_table_size;
-       hindex = IH_LOCAL_HASH(obj, size);
-
-       assert(entry == &table[index]);
-       assert(entry->ie_object == obj);
-
-       /*
-        *      We want to insert at hindex, but there may be collisions.
-        *      If a collision occurs, search for the end of the clump
-        *      and insert there.
-        */
-
-       while (table[hindex].ie_index != 0) {
-               if (++hindex == size)
-                       hindex = 0;
-       }
-
-       table[hindex].ie_index = index;
-}
-
-/*
- *     Routine:        ipc_hash_local_delete
- *     Purpose:
- *             Deletes an entry from the space's reverse hash table.
- *     Conditions:
- *             The space must be write-locked.
- */
-
-void
-ipc_hash_local_delete(
-       ipc_space_t             space,
-       ipc_object_t            obj,
-       mach_port_index_t       index,
-       ipc_entry_t             entry)
-{
-       ipc_entry_t table;
-       ipc_entry_num_t size;
-       mach_port_index_t hindex, dindex;
-
-       assert(index != MACH_PORT_NULL);
-       assert(space != IS_NULL);
-       assert(obj != IO_NULL);
-
-       table = space->is_table;
-       size = space->is_table_size;
-       hindex = IH_LOCAL_HASH(obj, size);
-
-       assert(entry == &table[index]);
-       assert(entry->ie_object == obj);
-
-       /*
-        *      First check we have the right hindex for this index.
-        *      In case of collision, we have to search farther
-        *      along in this clump.
-        */
-
-       while (table[hindex].ie_index != index) {
-               if (table[hindex].ie_index == 0)
-               {
-                       static int gak = 0;
-                       if (gak == 0)
-                       {
-                               printf("gak! entry wasn't in hash table!\n");
-                               gak = 1;
-                       }
-                       return;
-               }
-               if (++hindex == size)
-                       hindex = 0;
-       }
-
-       /*
-        *      Now we want to set table[hindex].ie_index = 0.
-        *      But if we aren't the last index in a clump,
-        *      this might cause problems for lookups of objects
-        *      farther along in the clump that are displaced
-        *      due to collisions.  Searches for them would fail
-        *      at hindex instead of succeeding.
-        *
-        *      So we must check the clump after hindex for objects
-        *      that are so displaced, and move one up to the new hole.
-        *
-        *              hindex - index of new hole in the clump
-        *              dindex - index we are checking for a displaced object
-        *
-        *      When we move a displaced object up into the hole,
-        *      it creates a new hole, and we have to repeat the process
-        *      until we get to the end of the clump.
-        */
-
-       for (dindex = hindex; index != 0; hindex = dindex) {
-               for (;;) {
-                       mach_port_index_t tindex;
-                       ipc_object_t tobj;
-
-                       if (++dindex == size)
-                               dindex = 0;
-                       assert(dindex != hindex);
-
-                       /* are we at the end of the clump? */
-
-                       index = table[dindex].ie_index;
-                       if (index == 0)
-                               break;
-
-                       /* is this a displaced object? */
-
-                       tobj = table[index].ie_object;
-                       assert(tobj != IO_NULL);
-                       tindex = IH_LOCAL_HASH(tobj, size);
-
-                       if ((dindex < hindex) ?
-                           ((dindex < tindex) && (tindex <= hindex)) :
-                           ((dindex < tindex) || (tindex <= hindex)))
-                               break;
-               }
-
-               table[hindex].ie_index = index;
-       }
-}
-
-/*
- *     Routine:        ipc_hash_init
- *     Purpose:
- *             Initialize the reverse hash table implementation.
- */
-
-void
-ipc_hash_init(void)
-{
-       ipc_hash_index_t i;
-
-       /* initialize ipc_hash_global_size */
-
-       ipc_hash_global_size = IPC_HASH_GLOBAL_SIZE;
-
-       /* make sure it is a power of two */
-
-       ipc_hash_global_mask = ipc_hash_global_size - 1;
-       if ((ipc_hash_global_size & ipc_hash_global_mask) != 0) {
-               natural_t bit;
-
-               /* round up to closest power of two */
-
-               for (bit = 1;; bit <<= 1) {
-                       ipc_hash_global_mask |= bit;
-                       ipc_hash_global_size = ipc_hash_global_mask + 1;
-
-                       if ((ipc_hash_global_size & ipc_hash_global_mask) == 0)
-                               break;
-               }
-       }
-
-       /* allocate ipc_hash_global_table */
-
-       ipc_hash_global_table = (ipc_hash_global_bucket_t)
-               kalloc((vm_size_t) (ipc_hash_global_size *
-                                   sizeof(struct ipc_hash_global_bucket)));
-       assert(ipc_hash_global_table != IHGB_NULL);
-
-       /* and initialize it */
-
-       for (i = 0; i < ipc_hash_global_size; i++) {
-               ipc_hash_global_bucket_t bucket;
-
-               bucket = &ipc_hash_global_table[i];
-               ihgb_lock_init(bucket);
-               bucket->ihgb_head = ITE_NULL;
-       }
-}
-
-#if    MACH_IPC_DEBUG
-
-/*
- *     Routine:        ipc_hash_info
- *     Purpose:
- *             Return information about the global reverse hash table.
- *             Fills the buffer with as much information as possible
- *             and returns the desired size of the buffer.
- *     Conditions:
- *             Nothing locked.  The caller should provide
- *             possibly-pageable memory.
- */
-
-
-ipc_hash_index_t
-ipc_hash_info(
-       hash_info_bucket_t      *info,
-       mach_msg_type_number_t count)
-{
-       ipc_hash_index_t i;
-
-       if (ipc_hash_global_size < count)
-               count = ipc_hash_global_size;
-
-       for (i = 0; i < count; i++) {
-               ipc_hash_global_bucket_t bucket = &ipc_hash_global_table[i];
-               unsigned int bucket_count = 0;
-               ipc_tree_entry_t entry;
-
-               ihgb_lock(bucket);
-               for (entry = bucket->ihgb_head;
-                    entry != ITE_NULL;
-                    entry = entry->ite_next)
-                       bucket_count++;
-               ihgb_unlock(bucket);
-
-               /* don't touch pageable memory while holding locks */
-               info[i].hib_count = bucket_count;
-       }
-
-       return ipc_hash_global_size;
-}
-
-#endif /* MACH_IPC_DEBUG */
diff --git a/ipc/ipc_hash.h b/ipc/ipc_hash.h
deleted file mode 100644
index 929ba77..0000000
--- a/ipc/ipc_hash.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989 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  address@hidden
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- *     File:   ipc/ipc_hash.h
- *     Author: Rich Draves
- *     Date:   1989
- *
- *     Declarations of entry hash table operations.
- */
-
-#ifndef        _IPC_IPC_HASH_H_
-#define _IPC_IPC_HASH_H_
-
-#include <mach/boolean.h>
-#include <mach/kern_return.h>
-
-typedef natural_t ipc_hash_index_t;
-
-extern void
-ipc_hash_init(void);
-
-#if    MACH_IPC_DEBUG
-
-extern ipc_hash_index_t
-ipc_hash_info(hash_info_bucket_t *, mach_msg_type_number_t);
-
-#endif /* MACH_IPC_DEBUG */
-
-extern boolean_t
-ipc_hash_lookup(ipc_space_t space, ipc_object_t obj,
-               mach_port_t *namep, ipc_entry_t *entryp);
-
-extern void
-ipc_hash_insert(ipc_space_t space, ipc_object_t obj,
-               mach_port_t name, ipc_entry_t entry);
-
-extern void
-ipc_hash_delete(ipc_space_t space, ipc_object_t obj,
-               mach_port_t name, ipc_entry_t entry);
-
-/*
- *     For use by functions that know what they're doing:
- *     the global primitives, for splay tree entries,
- *     and the local primitives, for table entries.
- */
-
-#define        IPC_HASH_GLOBAL_SIZE    256
-
-extern boolean_t
-ipc_hash_global_lookup(ipc_space_t space, ipc_object_t obj,
-                      mach_port_t *namep, ipc_tree_entry_t *entryp);
-
-extern void
-ipc_hash_global_insert(ipc_space_t space, ipc_object_t obj,
-                      mach_port_t name, ipc_tree_entry_t entry);
-
-extern void
-ipc_hash_global_delete(ipc_space_t space, ipc_object_t obj,
-                      mach_port_t name, ipc_tree_entry_t entry);
-
-extern boolean_t
-ipc_hash_local_lookup(ipc_space_t space, ipc_object_t obj,
-                     mach_port_t *namep, ipc_entry_t *entryp);
-
-extern void
-ipc_hash_local_insert(ipc_space_t space, ipc_object_t obj,
-                     mach_port_index_t index, ipc_entry_t entry);
-
-extern void
-ipc_hash_local_delete(ipc_space_t space, ipc_object_t obj,
-                     mach_port_index_t index, ipc_entry_t entry);
-
-#endif /* _IPC_IPC_HASH_H_ */
diff --git a/ipc/ipc_init.c b/ipc/ipc_init.c
index debda47..2c58a6e 100644
--- a/ipc/ipc_init.c
+++ b/ipc/ipc_init.c
@@ -47,7 +47,6 @@
 #include <ipc/ipc_marequest.h>
 #include <ipc/ipc_notify.h>
 #include <ipc/ipc_kmsg.h>
-#include <ipc/ipc_hash.h>
 #include <ipc/ipc_init.h>
 
 
@@ -76,8 +75,8 @@ ipc_bootstrap(void)
        kmem_cache_init(&ipc_space_cache, "ipc_space",
                        sizeof(struct ipc_space), 0, NULL, NULL, NULL, 0);
 
-       kmem_cache_init(&ipc_tree_entry_cache, "ipc_tree_entry",
-                       sizeof(struct ipc_tree_entry), 0, NULL, NULL, NULL, 0);
+       kmem_cache_init(&ipc_entry_cache, "ipc_entry",
+                       sizeof(struct ipc_entry), 0, NULL, NULL, NULL, 0);
 
        kmem_cache_init(&ipc_object_caches[IOT_PORT], "ipc_port",
                        sizeof(struct ipc_port), 0, NULL, NULL, NULL, 0);
@@ -97,7 +96,6 @@ ipc_bootstrap(void)
 
        ipc_table_init();
        ipc_notify_init();
-       ipc_hash_init();
        ipc_marequest_init();
 }
 
diff --git a/ipc/ipc_kmsg.c b/ipc/ipc_kmsg.c
index 66643fd..5076809 100644
--- a/ipc/ipc_kmsg.c
+++ b/ipc/ipc_kmsg.c
@@ -50,7 +50,6 @@
 #include <vm/vm_user.h>
 #include <ipc/port.h>
 #include <ipc/ipc_entry.h>
-#include <ipc/ipc_hash.h>
 #include <ipc/ipc_kmsg.h>
 #include <ipc/ipc_thread.h>
 #include <ipc/ipc_marequest.h>
@@ -698,24 +697,14 @@ ipc_kmsg_copyin_header(
                if (!space->is_active)
                        goto abort_async;
 
-               /* optimized ipc_entry_lookup */
-
-           {
-               mach_port_index_t index = MACH_PORT_INDEX(dest_name);
-               mach_port_gen_t gen = MACH_PORT_GEN(dest_name);
-
-               if (index >= space->is_table_size)
+               entry = ipc_entry_lookup (space, dest_name);
+               if (entry == IE_NULL)
                        goto abort_async;
-
-               entry = &space->is_table[index];
                bits = entry->ie_bits;
 
-               /* check generation number and type bit */
-
-               if ((bits & (IE_BITS_GEN_MASK|MACH_PORT_TYPE_SEND)) !=
-                   (gen | MACH_PORT_TYPE_SEND))
+               /* check type bits */
+               if (IE_BITS_TYPE (bits) != MACH_PORT_TYPE_SEND)
                        goto abort_async;
-           }
 
                /* optimized ipc_right_copyin */
 
@@ -750,8 +739,6 @@ ipc_kmsg_copyin_header(
 
            case MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
                                MACH_MSG_TYPE_MAKE_SEND_ONCE): {
-               ipc_entry_num_t size;
-               ipc_entry_t table;
                ipc_entry_t entry;
                ipc_entry_bits_t bits;
                ipc_port_t dest_port, reply_port;
@@ -762,51 +749,28 @@ ipc_kmsg_copyin_header(
                if (!space->is_active)
                        goto abort_request;
 
-               size = space->is_table_size;
-               table = space->is_table;
-
-               /* optimized ipc_entry_lookup of dest_name */
-
-           {
-               mach_port_index_t index = MACH_PORT_INDEX(dest_name);
-               mach_port_gen_t gen = MACH_PORT_GEN(dest_name);
-
-               if (index >= size)
+               entry = ipc_entry_lookup (space, dest_name);
+               if (entry == IE_NULL)
                        goto abort_request;
-
-               entry = &table[index];
                bits = entry->ie_bits;
 
-               /* check generation number and type bit */
-
-               if ((bits & (IE_BITS_GEN_MASK|MACH_PORT_TYPE_SEND)) !=
-                   (gen | MACH_PORT_TYPE_SEND))
+               /* check type bits */
+               if (IE_BITS_TYPE (bits) != MACH_PORT_TYPE_SEND)
                        goto abort_request;
-           }
 
                assert(IE_BITS_UREFS(bits) > 0);
 
                dest_port = (ipc_port_t) entry->ie_object;
                assert(dest_port != IP_NULL);
 
-               /* optimized ipc_entry_lookup of reply_name */
-
-           {
-               mach_port_index_t index = MACH_PORT_INDEX(reply_name);
-               mach_port_gen_t gen = MACH_PORT_GEN(reply_name);
-
-               if (index >= size)
+               entry = ipc_entry_lookup (space, reply_name);
+               if (entry == IE_NULL)
                        goto abort_request;
-
-               entry = &table[index];
                bits = entry->ie_bits;
 
-               /* check generation number and type bit */
-
-               if ((bits & (IE_BITS_GEN_MASK|MACH_PORT_TYPE_RECEIVE)) !=
-                   (gen | MACH_PORT_TYPE_RECEIVE))
+               /* check type bits */
+               if (IE_BITS_TYPE (bits) != MACH_PORT_TYPE_RECEIVE)
                        goto abort_request;
-           }
 
                reply_port = (ipc_port_t) entry->ie_object;
                assert(reply_port != IP_NULL);
@@ -853,9 +817,6 @@ ipc_kmsg_copyin_header(
            }
 
            case MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0): {
-               mach_port_index_t index;
-               mach_port_gen_t gen;
-               ipc_entry_t table;
                ipc_entry_t entry;
                ipc_entry_bits_t bits;
                ipc_port_t dest_port;
@@ -869,24 +830,13 @@ ipc_kmsg_copyin_header(
                if (!space->is_active)
                        goto abort_reply;
 
-               /* optimized ipc_entry_lookup */
-
-               table = space->is_table;
-
-               index = MACH_PORT_INDEX(dest_name);
-               gen = MACH_PORT_GEN(dest_name);
-
-               if (index >= space->is_table_size)
+               entry = ipc_entry_lookup (space, dest_name);
+               if (entry == IE_NULL)
                        goto abort_reply;
-
-               entry = &table[index];
                bits = entry->ie_bits;
 
-               /* check generation number, collision bit, and type bit */
-
-               if ((bits & (IE_BITS_GEN_MASK|IE_BITS_COLLISION|
-                            MACH_PORT_TYPE_SEND_ONCE)) !=
-                   (gen | MACH_PORT_TYPE_SEND_ONCE))
+               /* check and type bits */
+               if (IE_BITS_TYPE (bits) != MACH_PORT_TYPE_SEND_ONCE)
                        goto abort_reply;
 
                /* optimized ipc_right_copyin */
@@ -910,12 +860,8 @@ ipc_kmsg_copyin_header(
                assert(dest_port->ip_sorights > 0);
                ip_unlock(dest_port);
 
-               /* optimized ipc_entry_dealloc */
-
-               entry->ie_next = table->ie_next;
-               table->ie_next = index;
-               entry->ie_bits = gen;
                entry->ie_object = IO_NULL;
+               ipc_entry_dealloc (space, dest_name, entry);
                is_write_unlock(space);
 
                msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
@@ -1766,6 +1712,7 @@ ipc_kmsg_copyout_header(
            case MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0): {
                mach_port_t dest_name;
                ipc_port_t nsrequest;
+               unsigned long payload;
 
                /* receiving an asynchronous message */
 
@@ -1784,6 +1731,7 @@ ipc_kmsg_copyout_header(
                        dest_name = dest->ip_receiver_name;
                else
                        dest_name = MACH_PORT_NULL;
+               payload = dest->ip_protected_payload;
 
                if ((--dest->ip_srights == 0) &&
                    ((nsrequest = dest->ip_nsrequest) != IP_NULL)) {
@@ -1805,8 +1753,7 @@ ipc_kmsg_copyout_header(
                        msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
                                MACH_MSGH_BITS(
                                        0, MACH_MSG_TYPE_PROTECTED_PAYLOAD));
-                       msg->msgh_protected_payload =
-                               dest->ip_protected_payload;
+                       msg->msgh_protected_payload = payload;
                }
                msg->msgh_remote_port = MACH_PORT_NULL;
                return MACH_MSG_SUCCESS;
@@ -1814,12 +1761,11 @@ ipc_kmsg_copyout_header(
 
            case MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND,
                                MACH_MSG_TYPE_PORT_SEND_ONCE): {
-               ipc_entry_t table;
-               mach_port_index_t index;
                ipc_entry_t entry;
                ipc_port_t reply = (ipc_port_t) msg->msgh_local_port;
                mach_port_t dest_name, reply_name;
                ipc_port_t nsrequest;
+               unsigned long payload;
 
                /* receiving a request message */
 
@@ -1827,8 +1773,7 @@ ipc_kmsg_copyout_header(
                        break;
 
                is_write_lock(space);
-               if (!space->is_active ||
-                   ((index = (table = space->is_table)->ie_next) == 0)) {
+               if (!space->is_active || space->is_free_list == NULL) {
                        is_write_unlock(space);
                        break;
                }
@@ -1858,11 +1803,14 @@ ipc_kmsg_copyout_header(
                assert(reply->ip_sorights > 0);
                ip_unlock(reply);
 
-               /* optimized ipc_entry_get */
-
-               entry = &table[index];
-               table->ie_next = entry->ie_next;
-               entry->ie_request = 0;
+               kern_return_t kr;
+               kr = ipc_entry_get (space, &reply_name, &entry);
+               if (kr) {
+                       ip_unlock(reply);
+                       ip_unlock(dest);
+                       is_write_unlock(space);
+                       break;
+               }
 
            {
                mach_port_gen_t gen;
@@ -1870,8 +1818,6 @@ ipc_kmsg_copyout_header(
                assert((entry->ie_bits &~ IE_BITS_GEN_MASK) == 0);
                gen = entry->ie_bits + IE_BITS_GEN_ONE;
 
-               reply_name = MACH_PORT_MAKE(index, gen);
-
                /* optimized ipc_right_copyout */
 
                entry->ie_bits = gen | (MACH_PORT_TYPE_SEND_ONCE | 1);
@@ -1890,6 +1836,7 @@ ipc_kmsg_copyout_header(
                        dest_name = dest->ip_receiver_name;
                else
                        dest_name = MACH_PORT_NULL;
+               payload = dest->ip_protected_payload;
 
                if ((--dest->ip_srights == 0) &&
                    ((nsrequest = dest->ip_nsrequest) != IP_NULL)) {
@@ -1912,8 +1859,7 @@ ipc_kmsg_copyout_header(
                        msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
                                MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE,
                                        MACH_MSG_TYPE_PROTECTED_PAYLOAD));
-                       msg->msgh_protected_payload =
-                               dest->ip_protected_payload;
+                       msg->msgh_protected_payload = payload;
                }
                msg->msgh_remote_port = reply_name;
                return MACH_MSG_SUCCESS;
@@ -1921,6 +1867,7 @@ ipc_kmsg_copyout_header(
 
            case MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0): {
                mach_port_t dest_name;
+               unsigned long payload;
 
                /* receiving a reply message */
 
@@ -1934,6 +1881,8 @@ ipc_kmsg_copyout_header(
 
                assert(dest->ip_sorights > 0);
 
+               payload = dest->ip_protected_payload;
+
                if (dest->ip_receiver == space) {
                        ip_release(dest);
                        dest->ip_sorights--;
@@ -1955,8 +1904,7 @@ ipc_kmsg_copyout_header(
                        msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
                                MACH_MSGH_BITS(0,
                                        MACH_MSG_TYPE_PROTECTED_PAYLOAD));
-                       msg->msgh_protected_payload =
-                               dest->ip_protected_payload;
+                       msg->msgh_protected_payload = payload;
                }
                msg->msgh_remote_port = MACH_PORT_NULL;
                return MACH_MSG_SUCCESS;
@@ -1973,6 +1921,7 @@ ipc_kmsg_copyout_header(
        mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
        ipc_port_t reply = (ipc_port_t) msg->msgh_local_port;
        mach_port_t dest_name, reply_name;
+       unsigned long payload;
 
        if (IP_VALID(reply)) {
                ipc_port_t notify_port;
@@ -2053,28 +2002,20 @@ ipc_kmsg_copyout_header(
                                goto copyout_dest;
                        }
 
-                       kr = ipc_entry_get(space, &reply_name, &entry);
+                       kr = ipc_entry_alloc(space, &reply_name, &entry);
                        if (kr != KERN_SUCCESS) {
                                ip_unlock(reply);
 
                                if (notify_port != IP_NULL)
                                        ipc_port_release_sonce(notify_port);
 
-                               /* space is locked */
-                               kr = ipc_entry_grow_table(space);
-                               if (kr != KERN_SUCCESS) {
-                                       /* space is unlocked */
-
-                                       if (kr == KERN_RESOURCE_SHORTAGE)
-                                               return (MACH_RCV_HEADER_ERROR|
-                                                       MACH_MSG_IPC_KERNEL);
-                                       else
-                                               return (MACH_RCV_HEADER_ERROR|
-                                                       MACH_MSG_IPC_SPACE);
-                               }
-                               /* space is locked again; start over */
-
-                               continue;
+                               is_write_unlock(space);
+                               if (kr == KERN_RESOURCE_SHORTAGE)
+                                       return (MACH_RCV_HEADER_ERROR|
+                                               MACH_MSG_IPC_KERNEL);
+                               else
+                                       return (MACH_RCV_HEADER_ERROR|
+                                               MACH_MSG_IPC_SPACE);
                        }
 
                        assert(IE_BITS_TYPE(entry->ie_bits)
@@ -2219,6 +2160,7 @@ ipc_kmsg_copyout_header(
         */
 
     copyout_dest:
+       payload = dest->ip_protected_payload;
 
        if (ip_active(dest)) {
                ipc_object_copyout_dest(space, (ipc_object_t) dest,
@@ -2255,8 +2197,9 @@ ipc_kmsg_copyout_header(
                msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
                                  MACH_MSGH_BITS(reply_type,
                                        MACH_MSG_TYPE_PROTECTED_PAYLOAD));
-               msg->msgh_protected_payload = dest->ip_protected_payload;
+               msg->msgh_protected_payload = payload;
        }
+
        msg->msgh_remote_port = reply_name;
     }
 
@@ -2314,12 +2257,13 @@ ipc_kmsg_copyout_object(
 
        ip_lock(port);
        if (!ip_active(port) ||
-           !ipc_hash_local_lookup(space, (ipc_object_t) port,
-                                  namep, &entry)) {
+           (entry = ipc_reverse_lookup(space,
+                                       (ipc_object_t) port)) == NULL) {
                ip_unlock(port);
                is_write_unlock(space);
                goto slow_copyout;
        }
+       *namep = entry->ie_name;
 
        /*
         *      Copyout the send right, incrementing urefs
diff --git a/ipc/ipc_kmsg.h b/ipc/ipc_kmsg.h
index 620785b..393c039 100644
--- a/ipc/ipc_kmsg.h
+++ b/ipc/ipc_kmsg.h
@@ -38,7 +38,7 @@
 #include <mach/message.h>
 #include <kern/assert.h>
 #include <kern/cpu_number.h>
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 #include <kern/kalloc.h>
 #include <ipc/ipc_marequest.h>
 #include <ipc/ipc_object.h>
diff --git a/ipc/ipc_mqueue.h b/ipc/ipc_mqueue.h
index f8a2f1e..2af5e02 100644
--- a/ipc/ipc_mqueue.h
+++ b/ipc/ipc_mqueue.h
@@ -37,7 +37,7 @@
 #include <mach/message.h>
 #include <kern/assert.h>
 #include <kern/lock.h>
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 #include <ipc/ipc_kmsg_queue.h>
 #include <ipc/ipc_kmsg.h>
 #include <ipc/ipc_thread.h>
diff --git a/ipc/ipc_object.c b/ipc/ipc_object.c
index db6ef01..2d84cf5 100644
--- a/ipc/ipc_object.c
+++ b/ipc/ipc_object.c
@@ -41,7 +41,6 @@
 #include <ipc/ipc_space.h>
 #include <ipc/ipc_entry.h>
 #include <ipc/ipc_object.h>
-#include <ipc/ipc_hash.h>
 #include <ipc/ipc_right.h>
 #include <ipc/ipc_notify.h>
 #include <ipc/ipc_pset.h>
@@ -630,15 +629,10 @@ ipc_object_copyout(
                        break;
                }
 
-               kr = ipc_entry_get(space, &name, &entry);
+               kr = ipc_entry_alloc(space, &name, &entry);
                if (kr != KERN_SUCCESS) {
-                       /* unlocks/locks space, so must start again */
-
-                       kr = ipc_entry_grow_table(space);
-                       if (kr != KERN_SUCCESS)
-                               return kr; /* space is unlocked */
-
-                       continue;
+                       is_write_unlock(space);
+                       return kr;
                }
 
                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
@@ -691,15 +685,10 @@ ipc_object_copyout_multiname(space, object, namep)
                        return KERN_INVALID_TASK;
                }
 
-               kr = ipc_entry_get(space, &name, &entry);
+               kr = ipc_entry_alloc(space, &name, &entry);
                if (kr != KERN_SUCCESS) {
-                       /* unlocks/locks space, so must start again */
-
-                       kr = ipc_entry_grow_table(space);
-                       if (kr != KERN_SUCCESS)
-                               return kr; /* space is unlocked */
-
-                       continue;
+                       is_write_unlock(space);
+                       return kr; /* space is unlocked */
                }
 
                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
diff --git a/ipc/ipc_object.h b/ipc/ipc_object.h
index b83bb5a..be5bea7 100644
--- a/ipc/ipc_object.h
+++ b/ipc/ipc_object.h
@@ -38,7 +38,7 @@
 #include <mach/message.h>
 #include <ipc/ipc_types.h>
 #include <kern/lock.h>
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 #include <kern/slab.h>
 
 typedef unsigned int ipc_object_refs_t;
diff --git a/ipc/ipc_port.c b/ipc/ipc_port.c
index 89a5d67..86a4ee2 100644
--- a/ipc/ipc_port.c
+++ b/ipc/ipc_port.c
@@ -1178,11 +1178,11 @@ ipc_port_alloc_special(ipc_space_t space)
 {
        ipc_port_t port;
 
-       port = (ipc_port_t) io_alloc(IOT_PORT);
+       port = ip_alloc();
        if (port == IP_NULL)
                return IP_NULL;
 
-       io_lock_init(&port->ip_object);
+       ip_lock_init(port);
        port->ip_references = 1;
        port->ip_object.io_bits = io_makebits(TRUE, IOT_PORT, 0);
 
diff --git a/ipc/ipc_port.h b/ipc/ipc_port.h
index 6914c71..ade6967 100644
--- a/ipc/ipc_port.h
+++ b/ipc/ipc_port.h
@@ -43,7 +43,7 @@
 #include <mach/kern_return.h>
 #include <mach/port.h>
 #include <kern/lock.h>
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 #include <kern/ipc_kobject.h>
 #include <ipc/ipc_mqueue.h>
 #include <ipc/ipc_table.h>
diff --git a/ipc/ipc_right.c b/ipc/ipc_right.c
index 503eb1f..773b3b1 100644
--- a/ipc/ipc_right.c
+++ b/ipc/ipc_right.c
@@ -43,7 +43,6 @@
 #include <ipc/ipc_entry.h>
 #include <ipc/ipc_space.h>
 #include <ipc/ipc_object.h>
-#include <ipc/ipc_hash.h>
 #include <ipc/ipc_port.h>
 #include <ipc/ipc_pset.h>
 #include <ipc/ipc_marequest.h>
@@ -142,7 +141,8 @@ ipc_right_reverse(
                return TRUE;
        }
 
-       if (ipc_hash_lookup(space, (ipc_object_t) port, namep, entryp)) {
+       if ((*entryp = ipc_reverse_lookup(space, (ipc_object_t) port))) {
+               *namep = (*entryp)->ie_name;
                assert((entry = *entryp) != IE_NULL);
                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_SEND);
                assert(port == (ipc_port_t) entry->ie_object);
@@ -392,7 +392,7 @@ ipc_right_check(
                        ipc_marequest_cancel(space, name);
                }
 
-               ipc_hash_delete(space, (ipc_object_t) port, name, entry);
+               ipc_reverse_remove(space, (ipc_object_t) port);
        } else {
                assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
                assert(IE_BITS_UREFS(bits) == 1);
@@ -423,7 +423,7 @@ ipc_right_check(
  *     Purpose:
  *             Cleans up an entry in a dead space.
  *             The entry isn't deallocated or removed
- *             from reverse hash tables.
+ *             from the reverse mappings.
  *     Conditions:
  *             The space is dead and unlocked.
  */
@@ -609,8 +609,7 @@ ipc_right_destroy(
                }
 
                if (type == MACH_PORT_TYPE_SEND)
-                       ipc_hash_delete(space, (ipc_object_t) port,
-                                       name, entry);
+                       ipc_reverse_remove(space, (ipc_object_t) port);
 
                ip_lock(port);
 
@@ -789,8 +788,7 @@ ipc_right_dealloc(
                        dnrequest = ipc_right_dncancel_macro(space, port,
                                                             name, entry);
 
-                       ipc_hash_delete(space, (ipc_object_t) port,
-                                       name, entry);
+                       ipc_reverse_remove(space, (ipc_object_t) port);
 
                        if (bits & IE_BITS_MAREQUEST)
                                ipc_marequest_cancel(space, name);
@@ -1134,8 +1132,7 @@ ipc_right_delta(
                                dnrequest = ipc_right_dncancel_macro(
                                                space, port, name, entry);
 
-                               ipc_hash_delete(space, (ipc_object_t) port,
-                                               name, entry);
+                               ipc_reverse_remove(space, (ipc_object_t) port);
 
                                if (bits & IE_BITS_MAREQUEST)
                                        ipc_marequest_cancel(space, name);
@@ -1410,8 +1407,8 @@ ipc_right_copyin(
                        assert(IE_BITS_UREFS(bits) > 0);
                        assert(port->ip_srights > 0);
 
-                       ipc_hash_insert(space, (ipc_object_t) port,
-                                       name, entry);
+                       entry->ie_name = name;
+                       ipc_reverse_insert(space, (ipc_object_t) port, entry);
 
                        ip_reference(port);
                } else {
@@ -1534,8 +1531,7 @@ ipc_right_copyin(
                                dnrequest = ipc_right_dncancel_macro(
                                                space, port, name, entry);
 
-                               ipc_hash_delete(space, (ipc_object_t) port,
-                                               name, entry);
+                               ipc_reverse_remove(space, (ipc_object_t) port);
 
                                if (bits & IE_BITS_MAREQUEST)
                                        ipc_marequest_cancel(space, name);
@@ -1796,8 +1792,7 @@ ipc_right_copyin_two(
                        dnrequest = ipc_right_dncancel_macro(space, port,
                                                             name, entry);
 
-                       ipc_hash_delete(space, (ipc_object_t) port,
-                                       name, entry);
+                       ipc_reverse_remove(space, (ipc_object_t) port);
 
                        if (bits & IE_BITS_MAREQUEST)
                                ipc_marequest_cancel(space, name);
@@ -1921,8 +1916,8 @@ ipc_right_copyout(
 
                        /* entry is locked holding ref, so can use port */
 
-                       ipc_hash_insert(space, (ipc_object_t) port,
-                                       name, entry);
+                       entry->ie_name = name;
+                       ipc_reverse_insert(space, (ipc_object_t) port, entry);
                }
 
                entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1;
@@ -1956,8 +1951,7 @@ ipc_right_copyout(
 
                        /* entry is locked holding ref, so can use port */
 
-                       ipc_hash_delete(space, (ipc_object_t) port,
-                                       name, entry);
+                       ipc_reverse_remove(space, (ipc_object_t) port);
                } else {
                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
                        assert(IE_BITS_UREFS(bits) == 0);
@@ -2083,7 +2077,7 @@ ipc_right_rename(
                ipc_marequest_rename(space, oname, nname);
        }
 
-       /* initialize nentry before letting ipc_hash_insert see it */
+       /* initialize nentry before letting ipc_reverse_insert see it */
 
        assert((nentry->ie_bits & IE_BITS_RIGHT_MASK) == 0);
        nentry->ie_bits |= bits & IE_BITS_RIGHT_MASK;
@@ -2097,8 +2091,9 @@ ipc_right_rename(
                port = (ipc_port_t) object;
                assert(port != IP_NULL);
 
-               ipc_hash_delete(space, (ipc_object_t) port, oname, oentry);
-               ipc_hash_insert(space, (ipc_object_t) port, nname, nentry);
+               ipc_reverse_remove(space, (ipc_object_t) port);
+               nentry->ie_name = nname;
+               ipc_reverse_insert(space, (ipc_object_t) port, nentry);
                break;
            }
 
diff --git a/ipc/ipc_space.c b/ipc/ipc_space.c
index ab55e83..894cf58 100644
--- a/ipc/ipc_space.c
+++ b/ipc/ipc_space.c
@@ -46,8 +46,6 @@
 #include <kern/slab.h>
 #include <ipc/port.h>
 #include <ipc/ipc_entry.h>
-#include <ipc/ipc_splay.h>
-#include <ipc/ipc_hash.h>
 #include <ipc/ipc_table.h>
 #include <ipc/ipc_port.h>
 #include <ipc/ipc_space.h>
@@ -82,6 +80,9 @@ ipc_space_release(
        ipc_space_release_macro(space);
 }
 
+/* A place-holder object for the zeroth entry.  */
+struct ipc_entry zero_entry;
+
 /*
  *     Routine:        ipc_space_create
  *     Purpose:
@@ -98,56 +99,27 @@ ipc_space_release(
 
 kern_return_t
 ipc_space_create(
-       ipc_table_size_t        initial,
        ipc_space_t             *spacep)
 {
        ipc_space_t space;
-       ipc_entry_t table;
-       ipc_entry_num_t new_size;
-       mach_port_index_t index;
 
        space = is_alloc();
        if (space == IS_NULL)
                return KERN_RESOURCE_SHORTAGE;
 
-       table = it_entries_alloc(initial);
-       if (table == IE_NULL) {
-               is_free(space);
-               return KERN_RESOURCE_SHORTAGE;
-       }
-
-       new_size = initial->its_size;
-       memset((void *) table, 0, new_size * sizeof(struct ipc_entry));
-
-       /*
-        *      Initialize the free list in the table.
-        *      Add the entries in reverse order, and
-        *      set the generation number to -1, so that
-        *      initial allocations produce "natural" names.
-        */
-
-       for (index = 0; index < new_size; index++) {
-               ipc_entry_t entry = &table[index];
-
-               entry->ie_bits = IE_BITS_GEN_MASK;
-               entry->ie_next = index+1;
-       }
-       table[new_size-1].ie_next = 0;
-
        is_ref_lock_init(space);
        space->is_references = 2;
 
        is_lock_init(space);
        space->is_active = TRUE;
-       space->is_growing = FALSE;
-       space->is_table = table;
-       space->is_table_size = new_size;
-       space->is_table_next = initial+1;
 
-       ipc_splay_tree_init(&space->is_tree);
-       space->is_tree_total = 0;
-       space->is_tree_small = 0;
-       space->is_tree_hash = 0;
+       rdxtree_init(&space->is_map);
+       rdxtree_init(&space->is_reverse_map);
+       /* The zeroth entry is reserved.  */
+       rdxtree_insert(&space->is_map, 0, &zero_entry);
+       space->is_size = 1;
+       space->is_free_list = NULL;
+       space->is_free_list_size = 0;
 
        *spacep = space;
        return KERN_SUCCESS;
@@ -201,10 +173,6 @@ void
 ipc_space_destroy(
        ipc_space_t     space)
 {
-       ipc_tree_entry_t tentry;
-       ipc_entry_t table;
-       ipc_entry_num_t size;
-       mach_port_index_t index;
        boolean_t active;
 
        assert(space != IS_NULL);
@@ -217,59 +185,25 @@ ipc_space_destroy(
        if (!active)
                return;
 
-       /*
-        *      If somebody is trying to grow the table,
-        *      we must wait until they finish and figure
-        *      out the space died.
-        */
+       ipc_entry_t entry;
+       struct rdxtree_iter iter;
+       rdxtree_for_each(&space->is_map, &iter, entry) {
+               if (entry->ie_name == MACH_PORT_NULL)
+                       continue;
 
-       is_read_lock(space);
-       while (space->is_growing) {
-               assert_wait((event_t) space, FALSE);
-               is_read_unlock(space);
-               thread_block((void (*)(void)) 0);
-               is_read_lock(space);
-       }
-       is_read_unlock(space);
-
-       /*
-        *      Now we can futz with it without having it locked.
-        */
-
-       table = space->is_table;
-       size = space->is_table_size;
-
-       for (index = 0; index < size; index++) {
-               ipc_entry_t entry = &table[index];
                mach_port_type_t type = IE_BITS_TYPE(entry->ie_bits);
 
                if (type != MACH_PORT_TYPE_NONE) {
                        mach_port_t name =
-                               MACH_PORT_MAKEB(index, entry->ie_bits);
+                               MACH_PORT_MAKEB(entry->ie_name, entry->ie_bits);
 
                        ipc_right_clean(space, name, entry);
                }
-       }
-
-       it_entries_free(space->is_table_next-1, table);
-
-       for (tentry = ipc_splay_traverse_start(&space->is_tree);
-            tentry != ITE_NULL;
-            tentry = ipc_splay_traverse_next(&space->is_tree, TRUE)) {
-               mach_port_type_t type = IE_BITS_TYPE(tentry->ite_bits);
-               mach_port_t name = tentry->ite_name;
-
-               assert(type != MACH_PORT_TYPE_NONE);
-
-               /* use object before ipc_right_clean releases ref */
-
-               if (type == MACH_PORT_TYPE_SEND)
-                       ipc_hash_global_delete(space, tentry->ite_object,
-                                              name, tentry);
 
-               ipc_right_clean(space, name, &tentry->ite_entry);
+               ie_free(entry);
        }
-       ipc_splay_traverse_finish(&space->is_tree);
+       rdxtree_remove_all(&space->is_map);
+       rdxtree_remove_all(&space->is_reverse_map);
 
        /*
         *      Because the space is now dead,
diff --git a/ipc/ipc_space.h b/ipc/ipc_space.h
index c4683d2..bbfee46 100644
--- a/ipc/ipc_space.h
+++ b/ipc/ipc_space.h
@@ -42,25 +42,18 @@
 #include <mach/boolean.h>
 #include <mach/kern_return.h>
 #include <mach/mach_types.h>
-#include <kern/macro_help.h>
+#include <machine/vm_param.h>
+#include <kern/macros.h>
 #include <kern/lock.h>
+#include <kern/rdxtree.h>
 #include <kern/slab.h>
-#include <ipc/ipc_splay.h>
+#include <ipc/ipc_entry.h>
 #include <ipc/ipc_types.h>
 
 /*
  *     Every task has a space of IPC capabilities.
  *     IPC operations like send and receive use this space.
  *     IPC kernel calls manipulate the space of the target task.
- *
- *     Every space has a non-NULL is_table with is_table_size entries.
- *     A space may have a NULL is_tree.  is_tree_small records the
- *     number of entries in the tree that, if the table were to grow
- *     to the next larger size, would move from the tree to the table.
- *
- *     is_growing marks when the table is in the process of growing.
- *     When the table is growing, it can't be freed or grown by another
- *     thread, because of krealloc/kmem_realloc's requirements.
  */
 
 typedef unsigned int ipc_space_refs_t;
@@ -71,16 +64,16 @@ struct ipc_space {
 
        decl_simple_lock_data(,is_lock_data)
        boolean_t is_active;            /* is the space alive? */
-       boolean_t is_growing;           /* is the space growing? */
-       ipc_entry_t is_table;           /* an array of entries */
-       ipc_entry_num_t is_table_size;  /* current size of table */
-       struct ipc_table_size *is_table_next; /* info for larger table */
-       struct ipc_splay_tree is_tree;  /* a splay tree of entries */
-       ipc_entry_num_t is_tree_total;  /* number of entries in the tree */
-       ipc_entry_num_t is_tree_small;  /* # of small entries in the tree */
-       ipc_entry_num_t is_tree_hash;   /* # of hashed entries in the tree */
+       struct rdxtree is_map;          /* a map of entries */
+       size_t is_size;                 /* number of entries */
+       struct rdxtree is_reverse_map;  /* maps objects to entries */
+       ipc_entry_t is_free_list;       /* a linked list of free entries */
+       size_t is_free_list_size;       /* number of free entries */
+#define IS_FREE_LIST_SIZE_LIMIT        64      /* maximum number of entries
+                                          in the free list */
 };
 
+
 #define        IS_NULL                 ((ipc_space_t) 0)
 
 extern struct kmem_cache ipc_space_cache;
@@ -131,8 +124,187 @@ extern void ipc_space_release(struct ipc_space *space);
 #define        is_reference(is)        ipc_space_reference(is)
 #define        is_release(is)          ipc_space_release(is)
 
-kern_return_t  ipc_space_create(ipc_table_size_t, ipc_space_t *);
+kern_return_t  ipc_space_create(ipc_space_t *);
 kern_return_t  ipc_space_create_special(struct ipc_space **);
 void           ipc_space_destroy(struct ipc_space *);
 
+/* IPC entry lookups.  */
+
+/*
+ *     Routine:        ipc_entry_lookup
+ *     Purpose:
+ *             Searches for an entry, given its name.
+ *     Conditions:
+ *             The space must be read or write locked throughout.
+ *             The space must be active.
+ */
+
+static inline ipc_entry_t
+ipc_entry_lookup(
+       ipc_space_t space,
+       mach_port_t name)
+{
+       ipc_entry_t entry;
+
+       assert(space->is_active);
+       entry = rdxtree_lookup(&space->is_map, (rdxtree_key_t) name);
+       if (entry != IE_NULL
+           && IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
+               entry = NULL;
+       assert((entry == IE_NULL) || IE_BITS_TYPE(entry->ie_bits));
+       return entry;
+}
+
+/*
+ *     Routine:        ipc_entry_get
+ *     Purpose:
+ *             Tries to allocate an entry out of the space.
+ *     Conditions:
+ *             The space is write-locked and active throughout.
+ *             An object may be locked.  Will not allocate memory.
+ *     Returns:
+ *             KERN_SUCCESS            A free entry was found.
+ *             KERN_NO_SPACE           No entry allocated.
+ */
+
+static inline kern_return_t
+ipc_entry_get(
+       ipc_space_t space,
+       mach_port_t *namep,
+       ipc_entry_t *entryp)
+{
+       mach_port_t new_name;
+       ipc_entry_t free_entry;
+
+       assert(space->is_active);
+
+       /* Get entry from the free list.  */
+       free_entry = space->is_free_list;
+       if (free_entry == IE_NULL)
+               return KERN_NO_SPACE;
+
+       space->is_free_list = free_entry->ie_next_free;
+       space->is_free_list_size -= 1;
+
+       /*
+        *      Initialize the new entry.  We need only
+        *      increment the generation number and clear ie_request.
+        */
+
+    {
+       mach_port_gen_t gen;
+
+       assert((free_entry->ie_bits &~ IE_BITS_GEN_MASK) == 0);
+       gen = free_entry->ie_bits + IE_BITS_GEN_ONE;
+       free_entry->ie_bits = gen;
+       free_entry->ie_request = 0;
+       new_name = MACH_PORT_MAKE(free_entry->ie_name, gen);
+    }
+
+       /*
+        *      The new name can't be MACH_PORT_NULL because index
+        *      is non-zero.  It can't be MACH_PORT_DEAD because
+        *      the table isn't allowed to grow big enough.
+        *      (See comment in ipc/ipc_table.h.)
+        */
+
+       assert(MACH_PORT_VALID(new_name));
+       assert(free_entry->ie_object == IO_NULL);
+
+       space->is_size += 1;
+       *namep = new_name;
+       *entryp = free_entry;
+       return KERN_SUCCESS;
+}
+
+/*
+ *     Routine:        ipc_entry_dealloc
+ *     Purpose:
+ *             Deallocates an entry from a space.
+ *     Conditions:
+ *             The space must be write-locked throughout.
+ *             The space must be active.
+ */
+
+static inline void
+ipc_entry_dealloc(
+       ipc_space_t     space,
+       mach_port_t     name,
+       ipc_entry_t     entry)
+{
+       assert(space->is_active);
+       assert(entry->ie_object == IO_NULL);
+       assert(entry->ie_request == 0);
+
+       if (space->is_free_list_size < IS_FREE_LIST_SIZE_LIMIT) {
+               space->is_free_list_size += 1;
+               entry->ie_bits &= IE_BITS_GEN_MASK;
+               entry->ie_next_free = space->is_free_list;
+               space->is_free_list = entry;
+       } else {
+               rdxtree_remove(&space->is_map, (rdxtree_key_t) name);
+               ie_free(entry);
+       }
+       space->is_size -= 1;
+}
+
+/* Reverse lookups.  */
+
+/* Cast a pointer to a suitable key.  */
+#define KEY(X)                                                         \
+       ({                                                              \
+               assert((((unsigned long) (X)) & 0x07) == 0);            \
+               ((unsigned long long)                                   \
+                (((unsigned long) (X) - VM_MIN_KERNEL_ADDRESS) >> 3)); \
+       })
+
+/* Insert (OBJ, ENTRY) pair into the reverse mapping.  SPACE must
+   be write-locked.  */
+static inline kern_return_t
+ipc_reverse_insert(ipc_space_t space,
+                  ipc_object_t obj,
+                  ipc_entry_t entry)
+{
+       assert(space != IS_NULL);
+       assert(obj != IO_NULL);
+       return (kern_return_t) rdxtree_insert(&space->is_reverse_map,
+                                             KEY(obj), entry);
+}
+
+/* Remove OBJ from the reverse mapping.  SPACE must be
+   write-locked.  */
+static inline ipc_entry_t
+ipc_reverse_remove(ipc_space_t space,
+                  ipc_object_t obj)
+{
+       assert(space != IS_NULL);
+       assert(obj != IO_NULL);
+       return rdxtree_remove(&space->is_reverse_map, KEY(obj));
+}
+
+/* Remove all entries from the reverse mapping.  SPACE must be
+   write-locked.  */
+static inline void
+ipc_reverse_remove_all(ipc_space_t space)
+{
+       assert(space != IS_NULL);
+       rdxtree_remove_all(&space->is_reverse_map);
+       assert(space->is_reverse_map.height == 0);
+       assert(space->is_reverse_map.root == NULL);
+}
+
+/* Return ENTRY related to OBJ, or NULL if no such entry is found in
+   the reverse mapping.  SPACE must be read-locked or
+   write-locked.  */
+static inline ipc_entry_t
+ipc_reverse_lookup(ipc_space_t space,
+                  ipc_object_t obj)
+{
+       assert(space != IS_NULL);
+       assert(obj != IO_NULL);
+       return rdxtree_lookup(&space->is_reverse_map, KEY(obj));
+}
+
+#undef KEY
+
 #endif /* _IPC_IPC_SPACE_H_ */
diff --git a/ipc/ipc_splay.c b/ipc/ipc_splay.c
deleted file mode 100644
index 6fb5bcb..0000000
--- a/ipc/ipc_splay.c
+++ /dev/null
@@ -1,920 +0,0 @@
-/* 
- * Mach Operating System
- * Copyright (c) 1991,1990,1989 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  address@hidden
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- * 
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- */
-/*
- *     File:   ipc/ipc_splay.c
- *     Author: Rich Draves
- *     Date:   1989
- *
- *     Primitive splay tree operations.
- */
-
-#include <mach/port.h>
-#include <kern/assert.h>
-#include <kern/macro_help.h>
-#include <ipc/ipc_entry.h>
-#include <ipc/ipc_splay.h>
-
-/*
- *     Splay trees are self-adjusting binary search trees.
- *     They have the following attractive properties:
- *             1) Space efficient; only two pointers per entry.
- *             2) Robust performance; amortized O(log n) per operation.
- *             3) Recursion not needed.
- *     This makes them a good fall-back data structure for those
- *     entries that don't fit into the lookup table.
- *
- *     The paper by Sleator and Tarjan, JACM v. 32, no. 3, pp. 652-686,
- *     describes the splaying operation.  ipc_splay_prim_lookup
- *     and ipc_splay_prim_assemble implement the top-down splay
- *     described on p. 669.
- *
- *     The tree is stored in an unassembled form.  If ist_root is null,
- *     then the tree has no entries.  Otherwise, ist_name records
- *     the value used for the last lookup.  ist_root points to the
- *     middle tree obtained from the top-down splay.  ist_ltree and
- *     ist_rtree point to left and right subtrees, whose entries
- *     are all smaller (larger) than those in the middle tree.
- *     ist_ltreep and ist_rtreep are pointers to fields in the
- *     left and right subtrees.  ist_ltreep points to the rchild field
- *     of the largest entry in ltree, and ist_rtreep points to the
- *     lchild field of the smallest entry in rtree.  The pointed-to
- *     fields aren't initialized.  If the left (right) subtree is null,
- *     then ist_ltreep (ist_rtreep) points to the ist_ltree (ist_rtree)
- *     field in the splay structure itself.
- *
- *     The primary advantage of the unassembled form is that repeated
- *     unsuccessful lookups are efficient.  In particular, an unsuccessful
- *     lookup followed by an insert only requires one splaying operation.
- *
- *     The traversal algorithm works via pointer inversion.
- *     When descending down the tree, child pointers are reversed
- *     to point back to the parent entry.  When ascending,
- *     the pointers are restored to their original value.
- *
- *     The biggest potential problem with the splay tree implementation
- *     is that the operations, even lookup, require an exclusive lock.
- *     If IPC spaces are protected with exclusive locks, then
- *     the splay tree doesn't require its own lock, and ist_lock/ist_unlock
- *     needn't do anything.  If IPC spaces are protected with read/write
- *     locks then ist_lock/ist_unlock should provide exclusive access.
- *
- *     If it becomes important to let lookups run in parallel,
- *     or if the restructuring makes lookups too expensive, then
- *     there is hope.  Use a read/write lock on the splay tree.
- *     Keep track of the number of entries in the tree.  When doing
- *     a lookup, first try a non-restructuring lookup with a read lock held,
- *     with a bound (based on log of size of the tree) on the number of
- *     entries to traverse.  If the lookup runs up against the bound,
- *     then take a write lock and do a reorganizing lookup.
- *     This way, if lookups only access roughly balanced parts
- *     of the tree, then lookups run in parallel and do no restructuring.
- *
- *     The traversal algorithm currently requires an exclusive lock.
- *     If that is a problem, the tree could be changed from an lchild/rchild
- *     representation to a leftmost child/right sibling representation.
- *     In conjunction with non-restructing lookups, this would let
- *     lookups and traversals all run in parallel.  But this representation
- *     is more complicated and would slow down the operations.
- */
-
-/*
- *     Boundary values to hand to ipc_splay_prim_lookup:
- */
-
-#define        MACH_PORT_SMALLEST      ((mach_port_t) 0)
-#define MACH_PORT_LARGEST      ((mach_port_t) ~0)
-
-/*
- *     Routine:        ipc_splay_prim_lookup
- *     Purpose:
- *             Searches for the node labeled name in the splay tree.
- *             Returns three nodes (treep, ltreep, rtreep) and
- *             two pointers to nodes (ltreepp, rtreepp).
- *
- *             ipc_splay_prim_lookup splits the supplied tree into
- *             three subtrees, left, middle, and right, returned
- *             in ltreep, treep, and rtreep.
- *
- *             If name is present in the tree, then it is at
- *             the root of the middle tree.  Otherwise, the root
- *             of the middle tree is the last node traversed.
- *
- *             ipc_splay_prim_lookup returns a pointer into
- *             the left subtree, to the rchild field of its
- *             largest node, in ltreepp.  It returns a pointer
- *             into the right subtree, to the lchild field of its
- *             smallest node, in rtreepp.
- */
-
-static void
-ipc_splay_prim_lookup(
-       mach_port_t             name,
-       ipc_tree_entry_t        tree,
-       ipc_tree_entry_t        *treep,
-       ipc_tree_entry_t        *ltreep,
-       ipc_tree_entry_t        **ltreepp,
-       ipc_tree_entry_t        *rtreep,
-       ipc_tree_entry_t        **rtreepp)
-{
-       mach_port_t tname;                      /* temp name */
-       ipc_tree_entry_t lchild, rchild;        /* temp child pointers */
-
-       assert(tree != ITE_NULL);
-
-#define        link_left                                       \
-MACRO_BEGIN                                            \
-       *ltreep = tree;                                 \
-       ltreep = &tree->ite_rchild;                     \
-       tree = *ltreep;                                 \
-MACRO_END
-
-#define        link_right                                      \
-MACRO_BEGIN                                            \
-       *rtreep = tree;                                 \
-       rtreep = &tree->ite_lchild;                     \
-       tree = *rtreep;                                 \
-MACRO_END
-
-#define rotate_left                                    \
-MACRO_BEGIN                                            \
-       ipc_tree_entry_t temp = tree;                   \
-                                                       \
-       tree = temp->ite_rchild;                        \
-       temp->ite_rchild = tree->ite_lchild;            \
-       tree->ite_lchild = temp;                        \
-MACRO_END
-
-#define rotate_right                                   \
-MACRO_BEGIN                                            \
-       ipc_tree_entry_t temp = tree;                   \
-                                                       \
-       tree = temp->ite_lchild;                        \
-       temp->ite_lchild = tree->ite_rchild;            \
-       tree->ite_rchild = temp;                        \
-MACRO_END
-
-       while (name != (tname = tree->ite_name)) {
-               if (name < tname) {
-                       /* descend to left */
-
-                       lchild = tree->ite_lchild;
-                       if (lchild == ITE_NULL)
-                               break;
-                       tname = lchild->ite_name;
-
-                       if ((name < tname) &&
-                           (lchild->ite_lchild != ITE_NULL))
-                               rotate_right;
-                       link_right;
-                       if ((name > tname) &&
-                           (lchild->ite_rchild != ITE_NULL))
-                               link_left;
-               } else {
-                       /* descend to right */
-
-                       rchild = tree->ite_rchild;
-                       if (rchild == ITE_NULL)
-                               break;
-                       tname = rchild->ite_name;
-
-                       if ((name > tname) &&
-                           (rchild->ite_rchild != ITE_NULL))
-                               rotate_left;
-                       link_left;
-                       if ((name < tname) &&
-                           (rchild->ite_lchild != ITE_NULL))
-                               link_right;
-               }
-
-               assert(tree != ITE_NULL);
-       }
-
-       *treep = tree;
-       *ltreepp = ltreep;
-       *rtreepp = rtreep;
-
-#undef link_left
-#undef link_right
-#undef rotate_left
-#undef rotate_right
-}
-
-/*
- *     Routine:        ipc_splay_prim_assemble
- *     Purpose:
- *             Assembles the results of ipc_splay_prim_lookup
- *             into a splay tree with the found node at the root.
- *
- *             ltree and rtree are by-reference so storing
- *             through ltreep and rtreep can change them.
- */
-
-static void
-ipc_splay_prim_assemble(
-       ipc_tree_entry_t        tree,
-       ipc_tree_entry_t        *ltree,
-       ipc_tree_entry_t        *ltreep,
-       ipc_tree_entry_t        *rtree,
-       ipc_tree_entry_t        *rtreep)
-{
-       assert(tree != ITE_NULL);
-
-       *ltreep = tree->ite_lchild;
-       *rtreep = tree->ite_rchild;
-
-       tree->ite_lchild = *ltree;
-       tree->ite_rchild = *rtree;
-}
-
-/*
- *     Routine:        ipc_splay_tree_init
- *     Purpose:
- *             Initialize a raw splay tree for use.
- */
-
-void
-ipc_splay_tree_init(
-       ipc_splay_tree_t        splay)
-{
-       splay->ist_root = ITE_NULL;
-}
-
-/*
- *     Routine:        ipc_splay_tree_pick
- *     Purpose:
- *             Picks and returns a random entry in a splay tree.
- *             Returns FALSE if the splay tree is empty.
- */
-
-boolean_t
-ipc_splay_tree_pick(
-       ipc_splay_tree_t        splay,
-       mach_port_t             *namep,
-       ipc_tree_entry_t        *entryp)
-{
-       ipc_tree_entry_t root;
-
-       ist_lock(splay);
-
-       root = splay->ist_root;
-       if (root != ITE_NULL) {
-               *namep = root->ite_name;
-               *entryp = root;
-       }
-
-       ist_unlock(splay);
-
-       return root != ITE_NULL;
-}
-
-/*
- *     Routine:        ipc_splay_tree_lookup
- *     Purpose:
- *             Finds an entry in a splay tree.
- *             Returns ITE_NULL if not found.
- */
-
-ipc_tree_entry_t
-ipc_splay_tree_lookup(
-       ipc_splay_tree_t        splay,
-       mach_port_t             name)
-{
-       ipc_tree_entry_t root;
-
-       ist_lock(splay);
-
-       root = splay->ist_root;
-       if (root != ITE_NULL) {
-               if (splay->ist_name != name) {
-                       ipc_splay_prim_assemble(root,
-                               &splay->ist_ltree, splay->ist_ltreep,
-                               &splay->ist_rtree, splay->ist_rtreep);
-                       ipc_splay_prim_lookup(name, root, &root,
-                               &splay->ist_ltree, &splay->ist_ltreep,
-                               &splay->ist_rtree, &splay->ist_rtreep);
-                       splay->ist_name = name;
-                       splay->ist_root = root;
-               }
-
-               if (name != root->ite_name)
-                       root = ITE_NULL;
-       }
-
-       ist_unlock(splay);
-
-       return root;
-}
-
-/*
- *     Routine:        ipc_splay_tree_insert
- *     Purpose:
- *             Inserts a new entry into a splay tree.
- *             The caller supplies a new entry.
- *             The name can't already be present in the tree.
- */
-
-void
-ipc_splay_tree_insert(
-       ipc_splay_tree_t        splay,
-       mach_port_t             name,
-       ipc_tree_entry_t        entry)
-{
-       ipc_tree_entry_t root;
-
-       assert(entry != ITE_NULL);
-
-       ist_lock(splay);
-
-       root = splay->ist_root;
-       if (root == ITE_NULL) {
-               entry->ite_lchild = ITE_NULL;
-               entry->ite_rchild = ITE_NULL;
-       } else {
-               if (splay->ist_name != name) {
-                       ipc_splay_prim_assemble(root,
-                               &splay->ist_ltree, splay->ist_ltreep,
-                               &splay->ist_rtree, splay->ist_rtreep);
-                       ipc_splay_prim_lookup(name, root, &root,
-                               &splay->ist_ltree, &splay->ist_ltreep,
-                               &splay->ist_rtree, &splay->ist_rtreep);
-               }
-
-               assert(root->ite_name != name);
-
-               if (name < root->ite_name) {
-                       assert(root->ite_lchild == ITE_NULL);
-
-                       *splay->ist_ltreep = ITE_NULL;
-                       *splay->ist_rtreep = root;
-               } else {
-                       assert(root->ite_rchild == ITE_NULL);
-
-                       *splay->ist_ltreep = root;
-                       *splay->ist_rtreep = ITE_NULL;
-               }
-
-               entry->ite_lchild = splay->ist_ltree;
-               entry->ite_rchild = splay->ist_rtree;
-       }
-
-       entry->ite_name = name;
-       splay->ist_root = entry;
-       splay->ist_name = name;
-       splay->ist_ltreep = &splay->ist_ltree;
-       splay->ist_rtreep = &splay->ist_rtree;
-
-       ist_unlock(splay);
-}
-
-/*
- *     Routine:        ipc_splay_tree_delete
- *     Purpose:
- *             Deletes an entry from a splay tree.
- *             The name must be present in the tree.
- *             Frees the entry.
- *
- *             The "entry" argument isn't currently used.
- *             Other implementations might want it, though.
- */
-
-void
-ipc_splay_tree_delete(
-       ipc_splay_tree_t        splay,
-       mach_port_t             name,
-       ipc_tree_entry_t        entry)
-{
-       ipc_tree_entry_t root, saved;
-
-       ist_lock(splay);
-
-       root = splay->ist_root;
-       assert(root != ITE_NULL);
-
-       if (splay->ist_name != name) {
-               ipc_splay_prim_assemble(root,
-                       &splay->ist_ltree, splay->ist_ltreep,
-                       &splay->ist_rtree, splay->ist_rtreep);
-               ipc_splay_prim_lookup(name, root, &root,
-                       &splay->ist_ltree, &splay->ist_ltreep,
-                       &splay->ist_rtree, &splay->ist_rtreep);
-       }
-
-       assert(root->ite_name == name);
-       assert(root == entry);
-
-       *splay->ist_ltreep = root->ite_lchild;
-       *splay->ist_rtreep = root->ite_rchild;
-       ite_free(root);
-
-       root = splay->ist_ltree;
-       saved = splay->ist_rtree;
-
-       if (root == ITE_NULL)
-               root = saved;
-       else if (saved != ITE_NULL) {
-               /*
-                *      Find the largest node in the left subtree, and splay it
-                *      to the root.  Then add the saved right subtree.
-                */
-
-               ipc_splay_prim_lookup(MACH_PORT_LARGEST, root, &root,
-                       &splay->ist_ltree, &splay->ist_ltreep,
-                       &splay->ist_rtree, &splay->ist_rtreep);
-               ipc_splay_prim_assemble(root,
-                       &splay->ist_ltree, splay->ist_ltreep,
-                       &splay->ist_rtree, splay->ist_rtreep);
-
-               assert(root->ite_rchild == ITE_NULL);
-               root->ite_rchild = saved;
-       }
-
-       splay->ist_root = root;
-       if (root != ITE_NULL) {
-               splay->ist_name = root->ite_name;
-               splay->ist_ltreep = &splay->ist_ltree;
-               splay->ist_rtreep = &splay->ist_rtree;
-       }
-
-       ist_unlock(splay);
-}
-
-/*
- *     Routine:        ipc_splay_tree_split
- *     Purpose:
- *             Split a splay tree.  Puts all entries smaller than "name"
- *             into a new tree, "small".
- *
- *             Doesn't do locking on "small", because nobody else
- *             should be fiddling with the uninitialized tree.
- */
-
-void
-ipc_splay_tree_split(
-       ipc_splay_tree_t        splay,
-       mach_port_t             name,
-       ipc_splay_tree_t        small)
-{
-       ipc_tree_entry_t root;
-
-       ipc_splay_tree_init(small);
-
-       ist_lock(splay);
-
-       root = splay->ist_root;
-       if (root != ITE_NULL) {
-               /* lookup name, to get it (or last traversed) to the top */
-
-               if (splay->ist_name != name) {
-                       ipc_splay_prim_assemble(root,
-                               &splay->ist_ltree, splay->ist_ltreep,
-                               &splay->ist_rtree, splay->ist_rtreep);
-                       ipc_splay_prim_lookup(name, root, &root,
-                               &splay->ist_ltree, &splay->ist_ltreep,
-                               &splay->ist_rtree, &splay->ist_rtreep);
-               }
-
-               if (root->ite_name < name) {
-                       /* root goes into small */
-
-                       *splay->ist_ltreep = root->ite_lchild;
-                       *splay->ist_rtreep = ITE_NULL;
-                       root->ite_lchild = splay->ist_ltree;
-                       assert(root->ite_rchild == ITE_NULL);
-
-                       small->ist_root = root;
-                       small->ist_name = root->ite_name;
-                       small->ist_ltreep = &small->ist_ltree;
-                       small->ist_rtreep = &small->ist_rtree;
-
-                       /* rtree goes into splay */
-
-                       root = splay->ist_rtree;
-                       splay->ist_root = root;
-                       if (root != ITE_NULL) {
-                               splay->ist_name = root->ite_name;
-                               splay->ist_ltreep = &splay->ist_ltree;
-                               splay->ist_rtreep = &splay->ist_rtree;
-                       }
-               } else {
-                       /* root stays in splay */
-
-                       *splay->ist_ltreep = root->ite_lchild;
-                       root->ite_lchild = ITE_NULL;
-
-                       splay->ist_root = root;
-                       splay->ist_name = name;
-                       splay->ist_ltreep = &splay->ist_ltree;
-
-                       /* ltree goes into small */
-
-                       root = splay->ist_ltree;
-                       small->ist_root = root;
-                       if (root != ITE_NULL) {
-                               small->ist_name = root->ite_name;
-                               small->ist_ltreep = &small->ist_ltree;
-                               small->ist_rtreep = &small->ist_rtree;
-                       }
-               }               
-       }
-
-       ist_unlock(splay);
-}
-
-/*
- *     Routine:        ipc_splay_tree_join
- *     Purpose:
- *             Joins two splay trees.  Merges the entries in "small",
- *             which must all be smaller than the entries in "splay",
- *             into "splay".
- */
-
-void
-ipc_splay_tree_join(
-       ipc_splay_tree_t        splay,
-       ipc_splay_tree_t        small)
-{
-       ipc_tree_entry_t sroot;
-
-       /* pull entries out of small */
-
-       ist_lock(small);
-
-       sroot = small->ist_root;
-       if (sroot != ITE_NULL) {
-               ipc_splay_prim_assemble(sroot,
-                       &small->ist_ltree, small->ist_ltreep,
-                       &small->ist_rtree, small->ist_rtreep);
-               small->ist_root = ITE_NULL;
-       }
-
-       ist_unlock(small);
-
-       /* put entries, if any, into splay */
-
-       if (sroot != ITE_NULL) {
-               ipc_tree_entry_t root;
-
-               ist_lock(splay);
-
-               root = splay->ist_root;
-               if (root == ITE_NULL) {
-                       root = sroot;
-               } else {
-                       /* get smallest entry in splay tree to top */
-
-                       if (splay->ist_name != MACH_PORT_SMALLEST) {
-                               ipc_splay_prim_assemble(root,
-                                       &splay->ist_ltree, splay->ist_ltreep,
-                                       &splay->ist_rtree, splay->ist_rtreep);
-                               ipc_splay_prim_lookup(MACH_PORT_SMALLEST,
-                                       root, &root,
-                                       &splay->ist_ltree, &splay->ist_ltreep,
-                                       &splay->ist_rtree, &splay->ist_rtreep);
-                       }
-
-                       ipc_splay_prim_assemble(root,
-                               &splay->ist_ltree, splay->ist_ltreep,
-                               &splay->ist_rtree, splay->ist_rtreep);
-
-                       assert(root->ite_lchild == ITE_NULL);
-                       assert(sroot->ite_name < root->ite_name);
-                       root->ite_lchild = sroot;
-               }
-
-               splay->ist_root = root;
-               splay->ist_name = root->ite_name;
-               splay->ist_ltreep = &splay->ist_ltree;
-               splay->ist_rtreep = &splay->ist_rtree;
-
-               ist_unlock(splay);
-       }
-}
-
-/*
- *     Routine:        ipc_splay_tree_bounds
- *     Purpose:
- *             Given a name, returns the largest value present
- *             in the tree that is smaller than or equal to the name,
- *             or ~0 if no such value exists.  Similarly, returns
- *             the smallest value present that is greater than or
- *             equal to the name, or 0 if no such value exists.
- *
- *             Hence, if
- *             lower = upper, then lower = name = upper
- *                             and name is present in the tree
- *             lower = ~0 and upper = 0,
- *                             then the tree is empty
- *             lower = ~0 and upper > 0, then name < upper
- *                             and upper is smallest value in tree
- *             lower < ~0 and upper = 0, then lower < name
- *                             and lower is largest value in tree
- *             lower < ~0 and upper > 0, then lower < name < upper
- *                             and they are tight bounds on name
- *
- *             (Note MACH_PORT_SMALLEST = 0 and MACH_PORT_LARGEST = ~0.)
- */
-
-void
-ipc_splay_tree_bounds(
-       ipc_splay_tree_t        splay,
-       mach_port_t             name,
-       mach_port_t             *lowerp, 
-       mach_port_t             *upperp)
-{
-       ipc_tree_entry_t root;
-
-       ist_lock(splay);
-
-       root = splay->ist_root;
-       if (root == ITE_NULL) {
-               *lowerp = MACH_PORT_LARGEST;
-               *upperp = MACH_PORT_SMALLEST;
-       } else {
-               mach_port_t rname;
-
-               if (splay->ist_name != name) {
-                       ipc_splay_prim_assemble(root,
-                               &splay->ist_ltree, splay->ist_ltreep,
-                               &splay->ist_rtree, splay->ist_rtreep);
-                       ipc_splay_prim_lookup(name, root, &root,
-                               &splay->ist_ltree, &splay->ist_ltreep,
-                               &splay->ist_rtree, &splay->ist_rtreep);
-                       splay->ist_name = name;
-                       splay->ist_root = root;
-               }
-
-               rname = root->ite_name;
-
-               /*
-                *      OK, it's a hack.  We convert the ltreep and rtreep
-                *      pointers back into real entry pointers,
-                *      so we can pick the names out of the entries.
-                */
-
-               if (rname <= name)
-                       *lowerp = rname;
-               else if (splay->ist_ltreep == &splay->ist_ltree)
-                       *lowerp = MACH_PORT_LARGEST;
-               else {
-                       ipc_tree_entry_t entry;
-
-                       entry = (ipc_tree_entry_t)
-                               ((char *)splay->ist_ltreep -
-                                ((char *)&root->ite_rchild -
-                                 (char *)root));
-                       *lowerp = entry->ite_name;
-               }
-
-               if (rname >= name)
-                       *upperp = rname;
-               else if (splay->ist_rtreep == &splay->ist_rtree)
-                       *upperp = MACH_PORT_SMALLEST;
-               else {
-                       ipc_tree_entry_t entry;
-
-                       entry = (ipc_tree_entry_t)
-                               ((char *)splay->ist_rtreep -
-                                ((char *)&root->ite_lchild -
-                                 (char *)root));
-                       *upperp = entry->ite_name;
-               }
-       }
-
-       ist_unlock(splay);
-}
-
-/*
- *     Routine:        ipc_splay_traverse_start
- *     Routine:        ipc_splay_traverse_next
- *     Routine:        ipc_splay_traverse_finish
- *     Purpose:
- *             Perform a symmetric order traversal of a splay tree.
- *     Usage:
- *             for (entry = ipc_splay_traverse_start(splay);
- *                  entry != ITE_NULL;
- *                  entry = ipc_splay_traverse_next(splay, delete)) {
- *                     do something with entry
- *             }
- *             ipc_splay_traverse_finish(splay);
- *
- *             If "delete" is TRUE, then the current entry
- *             is removed from the tree and deallocated.
- *
- *             During the traversal, the splay tree is locked.
- */
-
-ipc_tree_entry_t
-ipc_splay_traverse_start(
-       ipc_splay_tree_t        splay)
-{
-       ipc_tree_entry_t current, parent;
-
-       ist_lock(splay);
-
-       current = splay->ist_root;
-       if (current != ITE_NULL) {
-               ipc_splay_prim_assemble(current,
-                       &splay->ist_ltree, splay->ist_ltreep,
-                       &splay->ist_rtree, splay->ist_rtreep);
-
-               parent = ITE_NULL;
-
-               while (current->ite_lchild != ITE_NULL) {
-                       ipc_tree_entry_t next;
-
-                       next = current->ite_lchild;
-                       current->ite_lchild = parent;
-                       parent = current;
-                       current = next;
-               }
-
-               splay->ist_ltree = current;
-               splay->ist_rtree = parent;
-       }
-
-       return current;
-}
-
-ipc_tree_entry_t
-ipc_splay_traverse_next(
-       ipc_splay_tree_t        splay,
-       boolean_t               delete)
-{
-       ipc_tree_entry_t current, parent;
-
-       /* pick up where traverse_entry left off */
-
-       current = splay->ist_ltree;
-       parent = splay->ist_rtree;
-       assert(current != ITE_NULL);
-
-       if (!delete)
-               goto traverse_right;
-
-       /* we must delete current and patch the tree */
-
-       if (current->ite_lchild == ITE_NULL) {
-               if (current->ite_rchild == ITE_NULL) {
-                       /* like traverse_back, but with deletion */
-
-                       if (parent == ITE_NULL) {
-                               ite_free(current);
-
-                               splay->ist_root = ITE_NULL;
-                               return ITE_NULL;
-                       }
-
-                       if (current->ite_name < parent->ite_name) {
-                               ite_free(current);
-
-                               current = parent;
-                               parent = current->ite_lchild;
-                               current->ite_lchild = ITE_NULL;
-                               goto traverse_entry;
-                       } else {
-                               ite_free(current);
-
-                               current = parent;
-                               parent = current->ite_rchild;
-                               current->ite_rchild = ITE_NULL;
-                               goto traverse_back;
-                       }
-               } else {
-                       ipc_tree_entry_t prev;
-
-                       prev = current;
-                       current = current->ite_rchild;
-                       ite_free(prev);
-                       goto traverse_left;
-               }
-       } else {
-               if (current->ite_rchild == ITE_NULL) {
-                       ipc_tree_entry_t prev;
-
-                       prev = current;
-                       current = current->ite_lchild;
-                       ite_free(prev);
-                       goto traverse_back;
-               } else {
-                       ipc_tree_entry_t prev;
-                       ipc_tree_entry_t ltree, rtree;
-                       ipc_tree_entry_t *ltreep, *rtreep;
-
-                       /* replace current with largest of left children */
-
-                       prev = current;
-                       ipc_splay_prim_lookup(MACH_PORT_LARGEST,
-                               current->ite_lchild, &current,
-                               &ltree, &ltreep, &rtree, &rtreep);
-                       ipc_splay_prim_assemble(current,
-                               &ltree, ltreep, &rtree, rtreep);
-
-                       assert(current->ite_rchild == ITE_NULL);
-                       current->ite_rchild = prev->ite_rchild;
-                       ite_free(prev);
-                       goto traverse_right;
-               }
-       }
-       /*NOTREACHED*/
-
-       /*
-        *      A state machine:  for each entry, we
-        *              1) traverse left subtree
-        *              2) traverse the entry
-        *              3) traverse right subtree
-        *              4) traverse back to parent
-        */
-
-    traverse_left:
-       if (current->ite_lchild != ITE_NULL) {
-               ipc_tree_entry_t next;
-
-               next = current->ite_lchild;
-               current->ite_lchild = parent;
-               parent = current;
-               current = next;
-               goto traverse_left;
-       }
-
-    traverse_entry:
-       splay->ist_ltree = current;
-       splay->ist_rtree = parent;
-       return current;
-
-    traverse_right:
-       if (current->ite_rchild != ITE_NULL) {
-               ipc_tree_entry_t next;
-
-               next = current->ite_rchild;
-               current->ite_rchild = parent;
-               parent = current;
-               current = next;
-               goto traverse_left;
-       }
-
-    traverse_back:
-       if (parent == ITE_NULL) {
-               splay->ist_root = current;
-               return ITE_NULL;
-       }
-
-       if (current->ite_name < parent->ite_name) {
-               ipc_tree_entry_t prev;
-
-               prev = current;
-               current = parent;
-               parent = current->ite_lchild;
-               current->ite_lchild = prev;
-               goto traverse_entry;
-       } else {
-               ipc_tree_entry_t prev;
-
-               prev = current;
-               current = parent;
-               parent = current->ite_rchild;
-               current->ite_rchild = prev;
-               goto traverse_back;
-       }
-}
-
-void
-ipc_splay_traverse_finish(
-       ipc_splay_tree_t        splay)
-{
-       ipc_tree_entry_t root;
-
-       root = splay->ist_root;
-       if (root != ITE_NULL) {
-               splay->ist_name = root->ite_name;
-               splay->ist_ltreep = &splay->ist_ltree;
-               splay->ist_rtreep = &splay->ist_rtree;
-       }
-
-       ist_unlock(splay);
-}
-
diff --git a/ipc/ipc_splay.h b/ipc/ipc_splay.h
deleted file mode 100644
index d3316ef..0000000
--- a/ipc/ipc_splay.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* 
- * Mach Operating System
- * Copyright (c) 1991,1990,1989 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  address@hidden
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- * 
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- */
-/*
- *     File:   ipc/ipc_splay.h
- *     Author: Rich Draves
- *     Date:   1989
- *
- *     Declarations of primitive splay tree operations.
- */
-
-#ifndef        _IPC_IPC_SPLAY_H_
-#define _IPC_IPC_SPLAY_H_
-
-#include <mach/port.h>
-#include <kern/assert.h>
-#include <kern/macro_help.h>
-#include <ipc/ipc_entry.h>
-
-typedef struct ipc_splay_tree {
-       mach_port_t ist_name;           /* name used in last lookup */
-       ipc_tree_entry_t ist_root;      /* root of middle tree */
-       ipc_tree_entry_t ist_ltree;     /* root of left tree */
-       ipc_tree_entry_t *ist_ltreep;   /* pointer into left tree */
-       ipc_tree_entry_t ist_rtree;     /* root of right tree */
-       ipc_tree_entry_t *ist_rtreep;   /* pointer into right tree */
-} *ipc_splay_tree_t;
-
-#define        ist_lock(splay)         /* no locking */
-#define ist_unlock(splay)      /* no locking */
-
-/* Initialize a raw splay tree */
-extern void ipc_splay_tree_init(
-       ipc_splay_tree_t        splay);
-
-/* Pick a random entry in a splay tree */
-extern boolean_t ipc_splay_tree_pick(
-       ipc_splay_tree_t        splay,
-       mach_port_t             *namep,
-       ipc_tree_entry_t        *entryp);
-
-/* Find an entry in a splay tree */
-extern ipc_tree_entry_t ipc_splay_tree_lookup(
-       ipc_splay_tree_t        splay,
-       mach_port_t             name);
-
-/* Insert a new entry into a splay tree */
-extern void ipc_splay_tree_insert(
-       ipc_splay_tree_t        splay,
-       mach_port_t             name,
-       ipc_tree_entry_t        entry);
-
-/* Delete an entry from a splay tree */
-extern void ipc_splay_tree_delete(
-       ipc_splay_tree_t        splay,
-       mach_port_t             name,
-       ipc_tree_entry_t        entry);
-
-/* Split a splay tree */
-extern void ipc_splay_tree_split(
-       ipc_splay_tree_t        splay,
-       mach_port_t             name,
-       ipc_splay_tree_t        entry);
-
-/* Join two splay trees */
-extern void ipc_splay_tree_join(
-       ipc_splay_tree_t        splay,
-       ipc_splay_tree_t        small);
-
-/* Do a bounded splay tree lookup */
-extern void ipc_splay_tree_bounds(
-       ipc_splay_tree_t        splay,
-       mach_port_t             name,
-       mach_port_t             *lowerp, 
-       mach_port_t             *upperp);
-
-/* Initialize a symmetric order traversal of a splay tree */
-extern ipc_tree_entry_t ipc_splay_traverse_start(
-       ipc_splay_tree_t        splay);
-
-/* Return the next entry in a symmetric order traversal of a splay tree */
-extern ipc_tree_entry_t ipc_splay_traverse_next(
-       ipc_splay_tree_t        splay,
-       boolean_t               delete);
-
-/* Terminate a symmetric order traversal of a splay tree */
-extern void ipc_splay_traverse_finish(
-       ipc_splay_tree_t        splay);
-
-#endif /* _IPC_IPC_SPLAY_H_ */
diff --git a/ipc/ipc_table.c b/ipc/ipc_table.c
index 90960a8..1a89d81 100644
--- a/ipc/ipc_table.c
+++ b/ipc/ipc_table.c
@@ -42,9 +42,6 @@
 #include <kern/slab.h>
 #include <vm/vm_kern.h>
 
-ipc_table_size_t ipc_table_entries;
-const unsigned int ipc_table_entries_size = 512;
-
 ipc_table_size_t ipc_table_dnrequests;
 const unsigned int ipc_table_dnrequests_size = 64;
 
@@ -92,20 +89,6 @@ ipc_table_fill(
 void
 ipc_table_init(void)
 {
-       ipc_table_entries = (ipc_table_size_t)
-               kalloc(sizeof(struct ipc_table_size) *
-                      ipc_table_entries_size);
-       assert(ipc_table_entries != ITS_NULL);
-
-       ipc_table_fill(ipc_table_entries, ipc_table_entries_size - 1,
-                      4, sizeof(struct ipc_entry));
-
-       /* the last two elements should have the same size */
-
-       ipc_table_entries[ipc_table_entries_size - 1].its_size =
-               ipc_table_entries[ipc_table_entries_size - 2].its_size;
-
-
        ipc_table_dnrequests = (ipc_table_size_t)
                kalloc(sizeof(struct ipc_table_size) *
                       ipc_table_dnrequests_size);
@@ -143,33 +126,6 @@ ipc_table_alloc(
 }
 
 /*
- *     Routine:        ipc_table_realloc
- *     Purpose:
- *             Reallocate a big table.
- *
- *             The new table remaps the old table,
- *             so copying is not necessary.
- *     Conditions:
- *             Only works for page-size or bigger tables.
- *             May block.
- */
-
-vm_offset_t
-ipc_table_realloc(
-       vm_size_t       old_size,
-       vm_offset_t     old_table,
-       vm_size_t       new_size)
-{
-       vm_offset_t new_table;
-
-       if (kmem_realloc(kmem_map, old_table, old_size,
-                        &new_table, new_size) != KERN_SUCCESS)
-               new_table = 0;
-
-       return new_table;
-}
-
-/*
  *     Routine:        ipc_table_free
  *     Purpose:
  *             Free a table allocated with ipc_table_alloc or
diff --git a/ipc/ipc_table.h b/ipc/ipc_table.h
index 311b9a7..7968e6b 100644
--- a/ipc/ipc_table.h
+++ b/ipc/ipc_table.h
@@ -30,8 +30,8 @@
  *     Author: Rich Draves
  *     Date:   1989
  *
- *     Definitions for tables, used for IPC capabilities (ipc_entry_t)
- *     and dead-name requests (ipc_port_request_t).
+ *     Definitions for tables, used for dead-name requests
+ *     (ipc_port_request_t).
  */
 
 #ifndef        _IPC_IPC_TABLE_H_
@@ -41,23 +41,8 @@
 #include <mach/vm_param.h>
 
 /*
- *     The is_table_next field of an ipc_space_t points to
- *     an ipc_table_size structure.  These structures must
- *     be elements of an array, ipc_table_entries.
- *
  *     Every its_size value must must be a power of two.
  *
- *     The array must end with two elements with the same its_size value.
- *     Except for the terminating element, the its_size values must
- *     be strictly increasing.  The largest (last) its_size value
- *     must be less than or equal to MACH_PORT_INDEX(MACH_PORT_DEAD).
- *     This ensures that
- *             1) MACH_PORT_INDEX(MACH_PORT_DEAD) isn't a valid index
- *             in the table, so ipc_entry_get won't allocate it.
- *             2) MACH_PORT_MAKE(index+1, 0) and MAKE_PORT_MAKE(size, 0)
- *             won't ever overflow.
- *
- *
  *     The ipr_size field of the first element in a table of
  *     dead-name requests (ipc_port_request_t) points to the
  *     ipc_table_size structure.  The structures must be elements
@@ -65,8 +50,6 @@
  *     with an element with zero its_size, and except for this last
  *     element, the its_size values must be strictly increasing.
  *
- *     The is_table_next field points to the ipc_table_size structure
- *     for the next larger size of table, not the one currently in use.
  *     The ipr_size field points to the currently used ipc_table_size.
  */
 
@@ -79,32 +62,21 @@ typedef struct ipc_table_size {
 
 #define        ITS_NULL        ((ipc_table_size_t) 0)
 
-extern ipc_table_size_t ipc_table_entries;
 extern ipc_table_size_t ipc_table_dnrequests;
 
 extern void
 ipc_table_init(void);
 
 /*
- *     Note that ipc_table_alloc, ipc_table_realloc, and ipc_table_free
- *     all potentially use the VM system.  Hence simple locks can't
- *     be held across them.
- *
- *     We can't use a copying realloc, because the realloc happens
- *     with the data unlocked.  ipc_table_realloc remaps the data,
- *     so it is OK.
+ *     Note that ipc_table_alloc, and ipc_table_free all potentially
+ *     use the VM system.  Hence simple locks can't be held across
+ *     them.
  */
 
 /* Allocate a table */
 extern vm_offset_t ipc_table_alloc(
        vm_size_t       size);
 
-/* Reallocate a big table */
-extern vm_offset_t ipc_table_realloc(
-       vm_size_t       old_size,
-       vm_offset_t     old_table,
-       vm_size_t       new_size);
-
 /* Free a table */
 extern void ipc_table_free(
        vm_size_t       size,
@@ -116,23 +88,6 @@ void ipc_table_fill(
        unsigned int            min,
        vm_size_t               elemsize);
 
-#define        it_entries_alloc(its)                                           
\
-       ((ipc_entry_t)                                                  \
-        ipc_table_alloc((its)->its_size * sizeof(struct ipc_entry)))
-
-#define it_entries_reallocable(its)                                    \
-       (((its)->its_size * sizeof(struct ipc_entry)) >= PAGE_SIZE)
-
-#define        it_entries_realloc(its, table, nits)                            
\
-       ((ipc_entry_t)                                                  \
-        ipc_table_realloc((its)->its_size * sizeof(struct ipc_entry),  \
-                          (vm_offset_t)(table),                        \
-                          (nits)->its_size * sizeof(struct ipc_entry)))
-
-#define        it_entries_free(its, table)                                     
\
-       ipc_table_free((its)->its_size * sizeof(struct ipc_entry),      \
-                      (vm_offset_t)(table))
-
 #define        it_dnrequests_alloc(its)                                        
\
        ((ipc_port_request_t)                                           \
         ipc_table_alloc((its)->its_size *                              \
diff --git a/ipc/mach_debug.c b/ipc/mach_debug.c
index eb52e1c..efb07a4 100644
--- a/ipc/mach_debug.c
+++ b/ipc/mach_debug.c
@@ -46,7 +46,6 @@
 #include <vm/vm_kern.h>
 #include <ipc/ipc_space.h>
 #include <ipc/ipc_port.h>
-#include <ipc/ipc_hash.h>
 #include <ipc/ipc_marequest.h>
 #include <ipc/ipc_table.h>
 #include <ipc/ipc_right.h>
@@ -94,85 +93,6 @@ mach_port_get_srights(
 }
 
 /*
- *     Routine:        host_ipc_hash_info
- *     Purpose:
- *             Return information about the global reverse hash table.
- *     Conditions:
- *             Nothing locked.  Obeys CountInOut protocol.
- *     Returns:
- *             KERN_SUCCESS            Returned information.
- *             KERN_INVALID_HOST       The host is null.
- *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
- */
-
-kern_return_t
-host_ipc_hash_info(
-       host_t                          host,
-       hash_info_bucket_array_t        *infop,
-       mach_msg_type_number_t          *countp)
-{
-       vm_offset_t addr;
-       vm_size_t size = 0;     /* Suppress gcc warning */
-       hash_info_bucket_t *info;
-       unsigned int potential, actual;
-       kern_return_t kr;
-
-       if (host == HOST_NULL)
-               return KERN_INVALID_HOST;
-
-       /* start with in-line data */
-
-       info = *infop;
-       potential = *countp;
-
-       for (;;) {
-               actual = ipc_hash_info(info, potential);
-               if (actual <= potential)
-                       break;
-
-               /* allocate more memory */
-
-               if (info != *infop)
-                       kmem_free(ipc_kernel_map, addr, size);
-
-               size = round_page(actual * sizeof *info);
-               kr = kmem_alloc_pageable(ipc_kernel_map, &addr, size);
-               if (kr != KERN_SUCCESS)
-                       return KERN_RESOURCE_SHORTAGE;
-
-               info = (hash_info_bucket_t *) addr;
-               potential = size/sizeof *info;
-       }
-
-       if (info == *infop) {
-               /* data fit in-line; nothing to deallocate */
-
-               *countp = actual;
-       } else if (actual == 0) {
-               kmem_free(ipc_kernel_map, addr, size);
-
-               *countp = 0;
-       } else {
-               vm_map_copy_t copy;
-               vm_size_t used;
-
-               used = round_page(actual * sizeof *info);
-
-               if (used != size)
-                       kmem_free(ipc_kernel_map, addr + used, size - used);
-
-               kr = vm_map_copyin(ipc_kernel_map, addr, used,
-                                  TRUE, &copy);
-               assert(kr == KERN_SUCCESS);
-
-               *infop = (hash_info_bucket_t *) copy;
-               *countp = actual;
-       }
-
-       return KERN_SUCCESS;
-}
-
-/*
  *     Routine:        host_ipc_marequest_info
  *     Purpose:
  *             Return information about the marequest hash table.
@@ -253,251 +173,6 @@ host_ipc_marequest_info(
 }
 
 /*
- *     Routine:        mach_port_space_info
- *     Purpose:
- *             Returns information about an IPC space.
- *     Conditions:
- *             Nothing locked.  Obeys CountInOut protocol.
- *     Returns:
- *             KERN_SUCCESS            Returned information.
- *             KERN_INVALID_TASK       The space is null.
- *             KERN_INVALID_TASK       The space is dead.
- *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
- */
-
-kern_return_t
-mach_port_space_info(
-       ipc_space_t                     space,
-       ipc_info_space_t                *infop,
-       ipc_info_name_array_t           *tablep,
-       mach_msg_type_number_t          *tableCntp,
-       ipc_info_tree_name_array_t      *treep,
-       mach_msg_type_number_t          *treeCntp)
-{
-       ipc_info_name_t *table_info;
-       unsigned int table_potential, table_actual;
-       vm_offset_t table_addr;
-       vm_size_t table_size = 0;       /* Suppress gcc warning */
-       ipc_info_tree_name_t *tree_info;
-       unsigned int tree_potential, tree_actual;
-       vm_offset_t tree_addr;
-       vm_size_t tree_size = 0;        /* Suppress gcc warning */
-       ipc_tree_entry_t tentry;
-       ipc_entry_t table;
-       ipc_entry_num_t tsize;
-       mach_port_index_t index;
-       kern_return_t kr;
-
-       if (space == IS_NULL)
-               return KERN_INVALID_TASK;
-
-       /* start with in-line memory */
-
-       table_info = *tablep;
-       table_potential = *tableCntp;
-       tree_info = *treep;
-       tree_potential = *treeCntp;
-
-       for (;;) {
-               is_read_lock(space);
-               if (!space->is_active) {
-                       is_read_unlock(space);
-                       if (table_info != *tablep)
-                               kmem_free(ipc_kernel_map,
-                                         table_addr, table_size);
-                       if (tree_info != *treep)
-                               kmem_free(ipc_kernel_map,
-                                         tree_addr, tree_size);
-                       return KERN_INVALID_TASK;
-               }
-
-               table_actual = space->is_table_size;
-               tree_actual = space->is_tree_total;
-
-               if ((table_actual <= table_potential) &&
-                   (tree_actual <= tree_potential))
-                       break;
-
-               is_read_unlock(space);
-
-               if (table_actual > table_potential) {
-                       if (table_info != *tablep)
-                               kmem_free(ipc_kernel_map,
-                                         table_addr, table_size);
-
-                       table_size = round_page(table_actual *
-                                               sizeof *table_info);
-                       kr = kmem_alloc(ipc_kernel_map,
-                                       &table_addr, table_size);
-                       if (kr != KERN_SUCCESS) {
-                               if (tree_info != *treep)
-                                       kmem_free(ipc_kernel_map,
-                                                 tree_addr, tree_size);
-
-                               return KERN_RESOURCE_SHORTAGE;
-                       }
-
-                       table_info = (ipc_info_name_t *) table_addr;
-                       table_potential = table_size/sizeof *table_info;
-               }
-
-               if (tree_actual > tree_potential) {
-                       if (tree_info != *treep)
-                               kmem_free(ipc_kernel_map,
-                                         tree_addr, tree_size);
-
-                       tree_size = round_page(tree_actual *
-                                              sizeof *tree_info);
-                       kr = kmem_alloc(ipc_kernel_map,
-                                       &tree_addr, tree_size);
-                       if (kr != KERN_SUCCESS) {
-                               if (table_info != *tablep)
-                                       kmem_free(ipc_kernel_map,
-                                                 table_addr, table_size);
-
-                               return KERN_RESOURCE_SHORTAGE;
-                       }
-
-                       tree_info = (ipc_info_tree_name_t *) tree_addr;
-                       tree_potential = tree_size/sizeof *tree_info;
-               }
-       }
-       /* space is read-locked and active; we have enough wired memory */
-
-       infop->iis_genno_mask = MACH_PORT_NGEN(MACH_PORT_DEAD);
-       infop->iis_table_size = space->is_table_size;
-       infop->iis_table_next = space->is_table_next->its_size;
-       infop->iis_tree_size = space->is_tree_total;
-       infop->iis_tree_small = space->is_tree_small;
-       infop->iis_tree_hash = space->is_tree_hash;
-
-       table = space->is_table;
-       tsize = space->is_table_size;
-
-       for (index = 0; index < tsize; index++) {
-               ipc_info_name_t *iin = &table_info[index];
-               ipc_entry_t entry = &table[index];
-               ipc_entry_bits_t bits = entry->ie_bits;
-
-               iin->iin_name = MACH_PORT_MAKEB(index, bits);
-               iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE;
-               iin->iin_compat = FALSE;
-               iin->iin_marequest = (bits & IE_BITS_MAREQUEST) ? TRUE : FALSE;
-               iin->iin_type = IE_BITS_TYPE(bits);
-               iin->iin_urefs = IE_BITS_UREFS(bits);
-               iin->iin_object = (vm_offset_t) entry->ie_object;
-               iin->iin_next = entry->ie_next;
-               iin->iin_hash = entry->ie_index;
-       }
-
-       for (tentry = ipc_splay_traverse_start(&space->is_tree), index = 0;
-            tentry != ITE_NULL;
-            tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) {
-               ipc_info_tree_name_t *iitn = &tree_info[index++];
-               ipc_info_name_t *iin = &iitn->iitn_name;
-               ipc_entry_t entry = &tentry->ite_entry;
-               ipc_entry_bits_t bits = entry->ie_bits;
-
-               assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE);
-
-               iin->iin_name = tentry->ite_name;
-               iin->iin_collision = (bits & IE_BITS_COLLISION) ? TRUE : FALSE;
-               iin->iin_compat = FALSE;
-               iin->iin_marequest = (bits & IE_BITS_MAREQUEST) ? TRUE : FALSE;
-               iin->iin_type = IE_BITS_TYPE(bits);
-               iin->iin_urefs = IE_BITS_UREFS(bits);
-               iin->iin_object = (vm_offset_t) entry->ie_object;
-               iin->iin_next = entry->ie_next;
-               iin->iin_hash = entry->ie_index;
-
-               if (tentry->ite_lchild == ITE_NULL)
-                       iitn->iitn_lchild = MACH_PORT_NULL;
-               else
-                       iitn->iitn_lchild = tentry->ite_lchild->ite_name;
-
-               if (tentry->ite_rchild == ITE_NULL)
-                       iitn->iitn_rchild = MACH_PORT_NULL;
-               else
-                       iitn->iitn_rchild = tentry->ite_rchild->ite_name;
-
-       }
-       ipc_splay_traverse_finish(&space->is_tree);
-       is_read_unlock(space);
-
-       if (table_info == *tablep) {
-               /* data fit in-line; nothing to deallocate */
-
-               *tableCntp = table_actual;
-       } else if (table_actual == 0) {
-               kmem_free(ipc_kernel_map, table_addr, table_size);
-
-               *tableCntp = 0;
-       } else {
-               vm_size_t size_used, rsize_used;
-               vm_map_copy_t copy;
-
-               /* kmem_alloc doesn't zero memory */
-
-               size_used = table_actual * sizeof *table_info;
-               rsize_used = round_page(size_used);
-
-               if (rsize_used != table_size)
-                       kmem_free(ipc_kernel_map,
-                                 table_addr + rsize_used,
-                                 table_size - rsize_used);
-
-               if (size_used != rsize_used)
-                       memset((void *) (table_addr + size_used), 0,
-                             rsize_used - size_used);
-
-               kr = vm_map_copyin(ipc_kernel_map, table_addr, rsize_used,
-                                  TRUE, &copy);
-
-               assert(kr == KERN_SUCCESS);
-
-               *tablep = (ipc_info_name_t *) copy;
-               *tableCntp = table_actual;
-       }
-
-       if (tree_info == *treep) {
-               /* data fit in-line; nothing to deallocate */
-
-               *treeCntp = tree_actual;
-       } else if (tree_actual == 0) {
-               kmem_free(ipc_kernel_map, tree_addr, tree_size);
-
-               *treeCntp = 0;
-       } else {
-               vm_size_t size_used, rsize_used;
-               vm_map_copy_t copy;
-
-               /* kmem_alloc doesn't zero memory */
-
-               size_used = tree_actual * sizeof *tree_info;
-               rsize_used = round_page(size_used);
-
-               if (rsize_used != tree_size)
-                       kmem_free(ipc_kernel_map,
-                                 tree_addr + rsize_used,
-                                 tree_size - rsize_used);
-
-               if (size_used != rsize_used)
-                       memset((void *) (tree_addr + size_used), 0,
-                             rsize_used - size_used);
-
-               kr = vm_map_copyin(ipc_kernel_map, tree_addr, rsize_used,
-                                  TRUE, &copy);
-
-               assert(kr == KERN_SUCCESS);
-
-               *treep = (ipc_info_tree_name_t *) copy;
-               *treeCntp = tree_actual;
-       }
-
-       return KERN_SUCCESS;
-}
-
-/*
  *     Routine:        mach_port_dnrequest_info
  *     Purpose:
  *             Returns information about the dead-name requests
diff --git a/ipc/mach_msg.c b/ipc/mach_msg.c
index 1e122c7..fe0c43e 100644
--- a/ipc/mach_msg.c
+++ b/ipc/mach_msg.c
@@ -482,16 +482,7 @@ mach_msg_trap(
                switch (kmsg->ikm_header.msgh_bits) {
                    case MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
                                        MACH_MSG_TYPE_MAKE_SEND_ONCE): {
-                       ipc_entry_t table;
-                       ipc_entry_num_t size;
                        ipc_port_t reply_port;
-
-                       /* sending a request message */
-
-                   {
-                       mach_port_index_t index;
-                       mach_port_gen_t gen;
-
                    {
                        mach_port_t reply_name =
                                kmsg->ikm_header.msgh_local_port;
@@ -499,68 +490,30 @@ mach_msg_trap(
                        if (reply_name != rcv_name)
                                goto slow_copyin;
 
-                       /* optimized ipc_entry_lookup of reply_name */
-
-                       index = MACH_PORT_INDEX(reply_name);
-                       gen = MACH_PORT_GEN(reply_name);
-                   }
-
                        is_read_lock(space);
                        assert(space->is_active);
 
-                       size = space->is_table_size;
-                       table = space->is_table;
-
-                       if (index >= size)
-                               goto abort_request_copyin;
-
-                   {
                        ipc_entry_t entry;
-                       ipc_entry_bits_t bits;
-
-                       entry = &table[index];
-                       bits = entry->ie_bits;
-
-                       /* check generation number and type bit */
-
-                       if ((bits & (IE_BITS_GEN_MASK|
-                                    MACH_PORT_TYPE_RECEIVE)) !=
-                           (gen | MACH_PORT_TYPE_RECEIVE))
+                       entry = ipc_entry_lookup (space, reply_name);
+                       if (entry == IE_NULL)
                                goto abort_request_copyin;
-
                        reply_port = (ipc_port_t) entry->ie_object;
                        assert(reply_port != IP_NULL);
                    }
-                   }
-
-                       /* optimized ipc_entry_lookup of dest_name */
-
-                   {
-                       mach_port_index_t index;
-                       mach_port_gen_t gen;
 
                    {
                        mach_port_t dest_name =
                                kmsg->ikm_header.msgh_remote_port;
 
-                       index = MACH_PORT_INDEX(dest_name);
-                       gen = MACH_PORT_GEN(dest_name);
-                   }
-
-                       if (index >= size)
-                               goto abort_request_copyin;
-
-                   {
                        ipc_entry_t entry;
                        ipc_entry_bits_t bits;
-
-                       entry = &table[index];
+                       entry = ipc_entry_lookup (space, dest_name);
+                       if (entry == IE_NULL)
+                               goto abort_request_copyin;
                        bits = entry->ie_bits;
 
-                       /* check generation number and type bit */
-
-                       if ((bits & (IE_BITS_GEN_MASK|MACH_PORT_TYPE_SEND)) !=
-                           (gen | MACH_PORT_TYPE_SEND))
+                       /* check type bits */
+                       if (IE_BITS_TYPE (bits) != MACH_PORT_TYPE_SEND)
                                goto abort_request_copyin;
 
                        assert(IE_BITS_UREFS(bits) > 0);
@@ -568,7 +521,6 @@ mach_msg_trap(
                        dest_port = (ipc_port_t) entry->ie_object;
                        assert(dest_port != IP_NULL);
                    }
-                   }
 
                        /*
                         *      To do an atomic copyin, need simultaneous
@@ -649,9 +601,6 @@ mach_msg_trap(
                    }
 
                    case MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0): {
-                       ipc_entry_num_t size;
-                       ipc_entry_t table;
-
                        /* sending a reply message */
 
                    {
@@ -665,35 +614,18 @@ mach_msg_trap(
                        is_write_lock(space);
                        assert(space->is_active);
 
-                       /* optimized ipc_entry_lookup */
-
-                       size = space->is_table_size;
-                       table = space->is_table;
-
                    {
                        ipc_entry_t entry;
-                       mach_port_gen_t gen;
-                       mach_port_index_t index;
-
-                   {
                        mach_port_t dest_name =
                                kmsg->ikm_header.msgh_remote_port;
 
-                       index = MACH_PORT_INDEX(dest_name);
-                       gen = MACH_PORT_GEN(dest_name);
-                   }
-
-                       if (index >= size)
+                       entry = ipc_entry_lookup (space, dest_name);
+                       if (entry == IE_NULL)
                                goto abort_reply_dest_copyin;
 
-                       entry = &table[index];
-
-                       /* check generation, collision bit, and type bit */
-
-                       if ((entry->ie_bits & (IE_BITS_GEN_MASK|
-                                              IE_BITS_COLLISION|
-                                              MACH_PORT_TYPE_SEND_ONCE)) !=
-                           (gen | MACH_PORT_TYPE_SEND_ONCE))
+                       /* check type bits */
+                       if (IE_BITS_TYPE (entry->ie_bits) !=
+                           MACH_PORT_TYPE_SEND_ONCE)
                                goto abort_reply_dest_copyin;
 
                        /* optimized ipc_right_copyin */
@@ -716,13 +648,8 @@ mach_msg_trap(
                        }
 
                        assert(dest_port->ip_sorights > 0);
-
-                       /* optimized ipc_entry_dealloc */
-
-                       entry->ie_next = table->ie_next;
-                       table->ie_next = index;
-                       entry->ie_bits = gen;
                        entry->ie_object = IO_NULL;
+                       ipc_entry_dealloc (space, dest_name, entry);
                    }
 
                        kmsg->ikm_header.msgh_bits =
@@ -735,31 +662,16 @@ mach_msg_trap(
 
                        assert(dest_port->ip_receiver != ipc_space_kernel);
 
-                       /* optimized ipc_entry_lookup/ipc_mqueue_copyin */
+                       /* optimized ipc_mqueue_copyin */
 
                    {
                        ipc_entry_t entry;
                        ipc_entry_bits_t bits;
-
-                   {
-                       mach_port_index_t index;
-                       mach_port_gen_t gen;
-
-                       index = MACH_PORT_INDEX(rcv_name);
-                       gen = MACH_PORT_GEN(rcv_name);
-
-                       if (index >= size)
+                       entry = ipc_entry_lookup (space, rcv_name);
+                       if (entry == IE_NULL)
                                goto abort_reply_rcv_copyin;
-
-                       entry = &table[index];
                        bits = entry->ie_bits;
 
-                       /* check generation number */
-
-                       if ((bits & IE_BITS_GEN_MASK) != gen)
-                               goto abort_reply_rcv_copyin;
-                   }
-
                        /* check type bits; looking for receive or set */
 
                        if (bits & MACH_PORT_TYPE_PORT_SET) {
@@ -1041,6 +953,7 @@ mach_msg_trap(
                        ipc_port_t reply_port =
                                (ipc_port_t) kmsg->ikm_header.msgh_local_port;
                        mach_port_t dest_name, reply_name;
+                       unsigned long payload;
 
                        /* receiving a request message */
 
@@ -1072,21 +985,12 @@ mach_msg_trap(
                        ip_unlock(reply_port);
 
                    {
-                       ipc_entry_t table;
                        ipc_entry_t entry;
-                       mach_port_index_t index;
-
-                       /* optimized ipc_entry_get */
-
-                       table = space->is_table;
-                       index = table->ie_next;
-
-                       if (index == 0)
+                       kern_return_t kr;
+                       kr = ipc_entry_get (space, &reply_name, &entry);
+                       if (kr)
                                goto abort_request_copyout;
-
-                       entry = &table[index];
-                       table->ie_next = entry->ie_next;
-                       entry->ie_request = 0;
+                       assert (entry != NULL);
 
                    {
                        mach_port_gen_t gen;
@@ -1094,8 +998,6 @@ mach_msg_trap(
                        assert((entry->ie_bits &~ IE_BITS_GEN_MASK) == 0);
                        gen = entry->ie_bits + IE_BITS_GEN_ONE;
 
-                       reply_name = MACH_PORT_MAKE(index, gen);
-
                        /* optimized ipc_right_copyout */
 
                        entry->ie_bits = gen | (MACH_PORT_TYPE_SEND_ONCE | 1);
@@ -1115,6 +1017,7 @@ mach_msg_trap(
                                dest_name = dest_port->ip_receiver_name;
                        else
                                dest_name = MACH_PORT_NULL;
+                       payload = dest_port->ip_protected_payload;
 
                        if ((--dest_port->ip_srights == 0) &&
                            (dest_port->ip_nsrequest != IP_NULL)) {
@@ -1142,7 +1045,7 @@ mach_msg_trap(
                                        MACH_MSG_TYPE_PORT_SEND_ONCE,
                                        MACH_MSG_TYPE_PROTECTED_PAYLOAD);
                                kmsg->ikm_header.msgh_protected_payload =
-                                       dest_port->ip_protected_payload;
+                                       payload;
                        }
                        kmsg->ikm_header.msgh_remote_port = reply_name;
                        goto fast_put;
@@ -1155,6 +1058,7 @@ mach_msg_trap(
 
                    case MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0): {
                        mach_port_t dest_name;
+                       unsigned long payload;
 
                        /* receiving a reply message */
 
@@ -1166,6 +1070,8 @@ mach_msg_trap(
 
                        assert(dest_port->ip_sorights > 0);
 
+                       payload = dest_port->ip_protected_payload;
+
                        if (dest_port->ip_receiver == space) {
                                ip_release(dest_port);
                                dest_port->ip_sorights--;
@@ -1188,7 +1094,7 @@ mach_msg_trap(
                                        0,
                                        MACH_MSG_TYPE_PROTECTED_PAYLOAD);
                                kmsg->ikm_header.msgh_protected_payload =
-                                       dest_port->ip_protected_payload;
+                                       payload;
                        }
                        kmsg->ikm_header.msgh_remote_port = MACH_PORT_NULL;
                        goto fast_put;
@@ -1197,6 +1103,7 @@ mach_msg_trap(
                    case MACH_MSGH_BITS_COMPLEX|
                         MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0): {
                        mach_port_t dest_name;
+                       unsigned long payload;
 
                        /* receiving a complex reply message */
 
@@ -1208,6 +1115,8 @@ mach_msg_trap(
 
                        assert(dest_port->ip_sorights > 0);
 
+                       payload = dest_port->ip_protected_payload;
+
                        if (dest_port->ip_receiver == space) {
                                ip_release(dest_port);
                                dest_port->ip_sorights--;
@@ -1234,7 +1143,7 @@ mach_msg_trap(
                                            0,
                                            MACH_MSG_TYPE_PROTECTED_PAYLOAD);
                                kmsg->ikm_header.msgh_protected_payload =
-                                       dest_port->ip_protected_payload;
+                                       payload;
                        }
                        kmsg->ikm_header.msgh_remote_port = MACH_PORT_NULL;
 
diff --git a/ipc/mach_port.c b/ipc/mach_port.c
index 4e89527..93a1248 100644
--- a/ipc/mach_port.c
+++ b/ipc/mach_port.c
@@ -150,10 +150,6 @@ mach_port_names(
        mach_port_type_t        **typesp,
        mach_msg_type_number_t  *typesCnt)
 {
-       ipc_tree_entry_t tentry;
-       ipc_entry_t table;
-       ipc_entry_num_t tsize;
-       mach_port_index_t index;
        ipc_entry_num_t actual; /* this many names */
        ipc_port_timestamp_t timestamp; /* logical time of this operation */
        mach_port_t *names;
@@ -190,7 +186,7 @@ mach_port_names(
 
                /* upper bound on number of names in the space */
 
-               bound = space->is_table_size + space->is_tree_total;
+               bound = space->is_size;
                size_needed = round_page(bound * sizeof(mach_port_t));
 
                if (size_needed <= size)
@@ -235,33 +231,16 @@ mach_port_names(
 
        timestamp = ipc_port_timestamp();
 
-       table = space->is_table;
-       tsize = space->is_table_size;
-
-       for (index = 0; index < tsize; index++) {
-               ipc_entry_t entry = &table[index];
+       ipc_entry_t entry;
+       struct rdxtree_iter iter;
+       rdxtree_for_each(&space->is_map, &iter, entry) {
                ipc_entry_bits_t bits = entry->ie_bits;
 
                if (IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE) {
-                       mach_port_t name = MACH_PORT_MAKEB(index, bits);
-
-                       mach_port_names_helper(timestamp, entry, name,
+                       mach_port_names_helper(timestamp, entry, entry->ie_name,
                                               names, types, &actual);
                }
        }
-
-       for (tentry = ipc_splay_traverse_start(&space->is_tree);
-            tentry != ITE_NULL;
-            tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) {
-               ipc_entry_t entry = &tentry->ite_entry;
-               mach_port_t name = tentry->ite_name;
-
-               assert(IE_BITS_TYPE(tentry->ite_bits) != MACH_PORT_TYPE_NONE);
-
-               mach_port_names_helper(timestamp, entry, name,
-                                      names, types, &actual);
-       }
-       ipc_splay_traverse_finish(&space->is_tree);
        is_read_unlock(space);
 
        if (actual == 0) {
@@ -946,10 +925,7 @@ mach_port_get_set_status(
        size = PAGE_SIZE;       /* initial guess */
 
        for (;;) {
-               ipc_tree_entry_t tentry;
-               ipc_entry_t entry, table;
-               ipc_entry_num_t tsize;
-               mach_port_index_t index;
+               ipc_entry_t entry;
                mach_port_t *names;
                ipc_pset_t pset;
 
@@ -986,11 +962,9 @@ mach_port_get_set_status(
                maxnames = size / sizeof(mach_port_t);
                actual = 0;
 
-               table = space->is_table;
-               tsize = space->is_table_size;
-
-               for (index = 0; index < tsize; index++) {
-                       ipc_entry_t ientry = &table[index];
+               ipc_entry_t ientry;
+               struct rdxtree_iter iter;
+               rdxtree_for_each(&space->is_map, &iter, ientry) {
                        ipc_entry_bits_t bits = ientry->ie_bits;
 
                        if (bits & MACH_PORT_TYPE_RECEIVE) {
@@ -1002,22 +976,6 @@ mach_port_get_set_status(
                        }
                }
 
-               for (tentry = ipc_splay_traverse_start(&space->is_tree);
-                    tentry != ITE_NULL;
-                    tentry = ipc_splay_traverse_next(&space->is_tree,FALSE)) {
-                       ipc_entry_bits_t bits = tentry->ite_bits;
-
-                       assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE);
-
-                       if (bits & MACH_PORT_TYPE_RECEIVE) {
-                               ipc_port_t port =
-                                       (ipc_port_t) tentry->ite_object;
-
-                               mach_port_gst_helper(pset, port, maxnames,
-                                                    names, &actual);
-                       }
-               }
-               ipc_splay_traverse_finish(&space->is_tree);
                is_read_unlock(space);
 
                if (actual <= maxnames)
diff --git a/device/blkio.h b/ipc/notify.defs
similarity index 64%
copy from device/blkio.h
copy to ipc/notify.defs
index 13a1669..db059b8 100644
--- a/device/blkio.h
+++ b/ipc/notify.defs
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Free Software Foundation.
+ * Copyright (c) 2015 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
@@ -11,14 +11,12 @@
  * 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.
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef _DEVICE_BLKIO_H_
-#define _DEVICE_BLKIO_H_
+/* We use custom functions to send notifications.  These functions can
+   be found in `ipc_notify.c'.  We use this file merely to produce the
+   list of message ids.  */
 
-extern vm_offset_t block_io_mmap(void);
-
-#endif /* _DEVICE_BLKIO_H_ */
+#include <mach/notify.defs>
diff --git a/ipc/port.h b/ipc/port.h
index d359115..49af6e2 100644
--- a/ipc/port.h
+++ b/ipc/port.h
@@ -45,10 +45,7 @@
  *     mach_port_t must be an unsigned type.  Port values
  *     have two parts, a generation number and an index.
  *     These macros encapsulate all knowledge of how
- *     a mach_port_t is laid out.  However, ipc/ipc_entry.c
- *     implicitly assumes when it uses the splay tree functions
- *     that the generation number is in the low bits, so that
- *     names are ordered first by index and then by generation.
+ *     a mach_port_t is laid out.
  *
  *     If the size of generation numbers changes,
  *     be sure to update IE_BITS_GEN_MASK and friends
diff --git a/kern/assert.h b/kern/assert.h
index bd2a8be..7b66d1b 100644
--- a/kern/assert.h
+++ b/kern/assert.h
@@ -29,7 +29,7 @@
 
 /*     assert.h        4.2     85/01/21        */
 
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 
 #ifndef NDEBUG
 #define MACH_ASSERT 1
diff --git a/kern/ast.h b/kern/ast.h
index 4c28b1e..7d472be 100644
--- a/kern/ast.h
+++ b/kern/ast.h
@@ -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/counters.c b/kern/counters.c
index 74fd42d..0a0665b 100644
--- a/kern/counters.c
+++ b/kern/counters.c
@@ -46,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 bfa9b44..aa1e739 100644
--- a/kern/counters.h
+++ b/kern/counters.h
@@ -69,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/exception.c b/kern/exception.c
index 7954fba..6cb3bfb 100644
--- a/kern/exception.c
+++ b/kern/exception.c
@@ -48,6 +48,7 @@
 #include <kern/sched.h>
 #include <kern/sched_prim.h>
 #include <kern/exception.h>
+#include <kern/macros.h>
 #include <mach/machine/vm_types.h>
 
 #if    MACH_KDB
@@ -603,30 +604,18 @@ exception_raise(
        ip_unlock(reply_port);
 
     {
-       ipc_entry_t table;
+       kern_return_t kr;
        ipc_entry_t entry;
-       mach_port_index_t index;
-
-       /* optimized ipc_entry_get */
 
-       table = space->is_table;
-       index = table->ie_next;
-
-       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;
-
     {
        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);
@@ -766,6 +755,12 @@ exception_raise(
     }
 }
 
+/* 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,
@@ -798,7 +793,7 @@ exception_parse_reply(ipc_kmsg_t 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.
                 */
diff --git a/kern/ipc_mig.c b/kern/ipc_mig.c
index cc61ec7..22dac42 100644
--- a/kern/ipc_mig.c
+++ b/kern/ipc_mig.c
@@ -310,16 +310,18 @@ mig_strncpy(dest, src, len)
 MACRO_BEGIN                                                            \
        ipc_space_t space = current_space();                            \
        ipc_entry_t entry;                                              \
-       mach_port_index_t index = MACH_PORT_INDEX(name);                \
                                                                        \
        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;                                                  \
        }                                                               \
                                                                        \
diff --git a/kern/ipc_tt.c b/kern/ipc_tt.c
index 96737be..e4d657b 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");
 
diff --git a/kern/list.h b/kern/list.h
index ad782a8..be92762 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.
diff --git a/kern/macro_help.h b/kern/macro_help.h
deleted file mode 100644
index 7ce171f..0000000
--- a/kern/macro_help.h
+++ /dev/null
@@ -1,50 +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  address@hidden
- *  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>
-
-#define                NEVER           FALSE
-#define                ALWAYS          TRUE
-
-#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 0000000..fb8dc5e
--- /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.h b/kern/pc_sample.h
index 3c64068..4832cb9 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.h b/kern/printf.h
index 0f8b328..86857d3 100644
--- a/kern/printf.h
+++ b/kern/printf.h
@@ -39,11 +39,16 @@ extern void printnum (unsigned 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 snprintf (char *buf, size_t size, 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/processor.c b/kern/processor.c
index 865c324..48e9273 100644
--- a/kern/processor.c
+++ b/kern/processor.c
@@ -657,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)
diff --git a/kern/rbtree.h b/kern/rbtree.h
index f577f7e..16ef273 100644
--- a/kern/rbtree.h
+++ b/kern/rbtree.h
@@ -31,12 +31,9 @@
 
 #include <stddef.h>
 #include <kern/assert.h>
-#include <kern/macro_help.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.
  */
@@ -177,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 0000000..78868b1
--- /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 0000000..1f8456e
--- /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 0000000..1bd1f64
--- /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 74204d6..f32feb8 100644
--- a/kern/refcount.h
+++ b/kern/refcount.h
@@ -27,7 +27,7 @@
 #ifndef        _KERN_REFCOUNT_H_
 #define _KERN_REFCOUNT_H_
 
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 
 /* Unless the above include file specified otherwise,
    use the system-independent (unoptimized) atomic reference counter.  */
diff --git a/kern/sched.h b/kern/sched.h
index ea601c5..f82f9f5 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>
diff --git a/kern/sched_prim.c b/kern/sched_prim.c
index d7792ae..e8f260e 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>
diff --git a/kern/sched_prim.h b/kern/sched_prim.h
index fd989b6..62698dc 100644
--- a/kern/sched_prim.h
+++ b/kern/sched_prim.h
@@ -150,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(
diff --git a/kern/slab.c b/kern/slab.c
index 19ebfed..60378b5 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))
diff --git a/kern/startup.c b/kern/startup.c
index 71cd04d..f9f0c34 100644
--- a/kern/startup.c
+++ b/kern/startup.c
@@ -41,6 +41,7 @@
 #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>
@@ -112,6 +113,7 @@ void setup_main(void)
 
        sched_init();
        vm_mem_bootstrap();
+       rdxtree_cache_init();
        ipc_bootstrap();
        vm_mem_init();
        ipc_init();
diff --git a/kern/syscall_subr.c b/kern/syscall_subr.c
index 3c369ef..6d23462 100644
--- a/kern/syscall_subr.c
+++ b/kern/syscall_subr.c
@@ -302,8 +302,8 @@ thread_depress_priority(
      * 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);
 
diff --git a/kern/task.c b/kern/task.c
index 57e7f41..b384347 100644
--- a/kern/task.c
+++ b/kern/task.c
@@ -89,9 +89,8 @@ kern_return_t task_create(
 #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;
@@ -1064,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;
 
diff --git a/kern/thread.c b/kern/thread.c
index 5ffa844..1f47553 100644
--- a/kern/thread.c
+++ b/kern/thread.c
@@ -124,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.
@@ -160,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;
        }
 }
@@ -175,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))
 {
@@ -199,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);
@@ -215,6 +211,7 @@ void stack_alloc(
        }
 
        stack_attach(thread, stack, resume);
+       return KERN_SUCCESS;
 }
 
 /*
@@ -235,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();
        }
 }
@@ -1667,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);
@@ -1974,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;
diff --git a/kern/thread_swap.c b/kern/thread_swap.c
index dc2924a..20ad040 100644
--- a/kern/thread_swap.c
+++ b/kern/thread_swap.c
@@ -123,15 +123,18 @@ void thread_swapin(thread_t 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_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.  
@@ -144,6 +147,7 @@ void thread_doswapin(thread_t thread)
                thread_setrun(thread, TRUE);
        thread_unlock(thread);
        (void) splx(s);
+       return KERN_SUCCESS;
 }
 
 /*
@@ -163,13 +167,20 @@ void __attribute__((noreturn)) 
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 9d64537..d032acc 100644
--- a/kern/thread_swap.h
+++ b/kern/thread_swap.h
@@ -37,7 +37,7 @@
  */
 extern void    swapper_init(void);
 extern void    thread_swapin(thread_t thread);
-extern void    thread_doswapin(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/timer.c b/kern/timer.c
index 6d6517e..79ada27 100644
--- a/kern/timer.c
+++ b/kern/timer.c
@@ -33,7 +33,7 @@
 #include <kern/cpu_number.h>
 
 #include <kern/assert.h>
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 
 
 
diff --git a/kern/timer.h b/kern/timer.h
index 57f017a..2f473cf 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
 /*
diff --git a/linux/Makefrag.am b/linux/Makefrag.am
index 0973f11..1b69010 100644
--- a/linux/Makefrag.am
+++ b/linux/Makefrag.am
@@ -36,6 +36,11 @@ liblinux_a_CPPFLAGS = $(AM_CPPFLAGS) \
 # Because of the use of `extern inline' in some Linux header files without
 # corresponding text segment definitions, we must always optimize.
 liblinux_a_CFLAGS = -O2 $(AM_CFLAGS)
+
+# See <http://lists.gnu.org/archive/html/bug-hurd/2006-01/msg00148.html>.
+liblinux_a_CFLAGS += \
+       -fno-strict-aliasing
+
 # TODO.  Do we really need `-traditional'?
 liblinux_a_CCASFLAGS = $(AM_CCASFLAGS) \
        -D__ASSEMBLY__ -traditional \
diff --git a/linux/dev/drivers/block/ahci.c b/linux/dev/drivers/block/ahci.c
index 868f8d0..9bb2e6b 100644
--- a/linux/dev/drivers/block/ahci.c
+++ b/linux/dev/drivers/block/ahci.c
@@ -638,6 +638,7 @@ static int ahci_identify(const volatile struct ahci_host 
*ahci_host, const volat
                        port->ahci_host = NULL;
                        port->ahci_port = NULL;
                        del_timer(&identify_timer);
+                       restore_flags(flags);
                        return 3;
                }
                sleep_on(&port->q);
@@ -877,6 +878,7 @@ static void ahci_probe_dev(unsigned char bus, unsigned char 
device)
 
        for (i = 0; i < AHCI_MAX_PORTS; i++) {
                u32 ssts;
+               u8 spd, ipm;
 
                if (!(port_map & (1U << i)))
                        continue;
@@ -884,12 +886,45 @@ static void ahci_probe_dev(unsigned char bus, unsigned 
char device)
                ahci_port = &ahci_host->ports[i];
 
                ssts = readl(&ahci_port->ssts);
-               if ((ssts & 0xf) != 0x3)
-                       /* Device not present */
-                       continue;
-               if (((ssts >> 8) & 0xf) != 0x1)
-                       /* Device down */
-                       continue;
+               spd = ssts & 0xf;
+               switch (spd)
+               {
+                       case 0x0:
+                               /* Device not present */
+                               continue;
+                       case 0x1:
+                               printk("ahci: %02u:%02u.%u: Port %u 
communication not established. TODO: power on device\n", bus, dev, fun, i);
+                               continue;
+                       case 0x3:
+                               /* Present and communication established */
+                               break;
+                       case 0x4:
+                               printk("ahci: %02u:%02u.%u: Phy offline?!\n", 
bus, dev, fun, i);
+                               continue;
+                       default:
+                               printk("ahci: %02u:%02u.%u: Unknown port %u SPD 
%x\n", bus, dev, fun, i, spd);
+                               continue;
+               }
+
+               ipm = (ssts >> 8) & 0xf;
+               switch (ipm)
+               {
+                       case 0x0:
+                               /* Device not present */
+                               continue;
+                       case 0x1:
+                               /* Active */
+                               break;
+                       case 0x2:
+                               printk("ahci: %02u:%02u.%u: Port %u in Partial 
power management. TODO: power on device\n", bus, dev, fun, i);
+                               continue;
+                       case 0x6:
+                               printk("ahci: %02u:%02u.%u: Port %u in Slumber 
power management. TODO: power on device\n", bus, dev, fun, i);
+                               continue;
+                       default:
+                               printk("ahci: %02u:%02u.%u: Unknown port %u IPM 
%x\n", bus, dev, fun, i, ipm);
+                               continue;
+               }
 
                /* OK! Probe this port */
                ahci_probe_port(ahci_host, ahci_port);
diff --git a/linux/dev/include/linux/types.h b/linux/dev/include/linux/types.h
index 57bb25f..b697d9e 100644
--- a/linux/dev/include/linux/types.h
+++ b/linux/dev/include/linux/types.h
@@ -109,6 +109,15 @@ struct ustat {
        char                    f_fpack[6];
 };
 
+/* stdint.h */
+typedef s8 int8_t;
+typedef u8 uint8_t;
+typedef s16 int16_t;
+typedef u16 uint16_t;
+typedef s32 int32_t;
+typedef u32 uint32_t;
+typedef s64 int64_t;
+typedef u64 uint64_t;
 
 /* Yes, this is ugly.  But that's why it is called glue code.  */
 
diff --git a/linux/src/include/asm-i386/bitops.h 
b/linux/src/include/asm-i386/bitops.h
index fc4cf19..0bfa9fd 100644
--- a/linux/src/include/asm-i386/bitops.h
+++ b/linux/src/include/asm-i386/bitops.h
@@ -108,6 +108,7 @@ extern __inline__ int test_bit(int nr, const SMPVOL void * 
addr)
  */
 extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
 {
+       int d0, d1, d2;
        int res;
 
        if (!size)
@@ -123,9 +124,8 @@ extern __inline__ int find_first_zero_bit(void * addr, 
unsigned size)
                "1:\tsubl %%ebx,%%edi\n\t"
                "shll $3,%%edi\n\t"
                "addl %%edi,%%edx"
-               :"=d" (res)
-               :"c" ((size + 31) >> 5), "D" (addr), "b" (addr)
-               :"ax", "cx", "di");
+               :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
+               :"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
        return res;
 }
 
diff --git a/linux/src/include/asm-i386/semaphore.h 
b/linux/src/include/asm-i386/semaphore.h
index 1486d1c..c351c3a 100644
--- a/linux/src/include/asm-i386/semaphore.h
+++ b/linux/src/include/asm-i386/semaphore.h
@@ -30,6 +30,10 @@ struct semaphore {
 #define MUTEX ((struct semaphore) { 1, 0, 0, NULL })
 #define MUTEX_LOCKED ((struct semaphore) { 0, 0, 0, NULL })
 
+/* Special register calling convention:
+ * eax contains return address
+ * ecx contains semaphore address
+ */
 asmlinkage void down_failed(void /* special register calling convention */);
 asmlinkage void up_wakeup(void /* special register calling convention */);
 
@@ -43,18 +47,19 @@ extern void __up(struct semaphore * sem);
  */
 extern inline void down(struct semaphore * sem)
 {
+       int d0;
        __asm__ __volatile__(
                "# atomic down operation\n\t"
                "movl $1f,%%eax\n\t"
 #ifdef __SMP__
                "lock ; "
 #endif
-               "decl 0(%0)\n\t"
+               "decl %1\n\t"
                "js " SYMBOL_NAME_STR(down_failed) "\n"
                "1:\n"
-               :/* no outputs */
+               :"=&a" (d0), "=m" (sem->count)
                :"c" (sem)
-               :"ax","dx","memory");
+               :"memory");
 }
 
 /*
@@ -91,13 +96,13 @@ extern inline int down_interruptible(struct semaphore * sem)
 #ifdef __SMP__
                 "lock ; "
 #endif
-                "decl 0(%1)\n\t"
+                "decl %1\n\t"
                 "js " SYMBOL_NAME_STR(down_failed_interruptible) "\n\t"
                 "xorl %%eax,%%eax\n"
                 "2:\n"
-                :"=a" (ret)
+                :"=&a" (ret), "=m" (sem->count)
                 :"c" (sem)
-                :"ax","dx","memory");
+                :"memory");
 
        return(ret) ;
 }
@@ -110,18 +115,19 @@ extern inline int down_interruptible(struct semaphore * 
sem)
  */
 extern inline void up(struct semaphore * sem)
 {
+       int d0;
        __asm__ __volatile__(
                "# atomic up operation\n\t"
                "movl $1f,%%eax\n\t"
 #ifdef __SMP__
                "lock ; "
 #endif
-               "incl 0(%0)\n\t"
+               "incl %1\n\t"
                "jle " SYMBOL_NAME_STR(up_wakeup)
                "\n1:"
-               :/* no outputs */
+               :"=&a" (d0), "=m" (sem->count)
                :"c" (sem)
-               :"ax", "dx", "memory");
+               :"memory");
 }
 
 #endif
diff --git a/linux/src/include/linux/compiler-gcc5.h 
b/linux/src/include/linux/compiler-gcc5.h
new file mode 100644
index 0000000..efee493
--- /dev/null
+++ b/linux/src/include/linux/compiler-gcc5.h
@@ -0,0 +1,67 @@
+#ifndef __LINUX_COMPILER_H
+#error "Please don't include <linux/compiler-gcc5.h> directly, include 
<linux/compiler.h> instead."
+#endif
+
+#define __used                         __attribute__((__used__))
+#define __must_check                   __attribute__((warn_unused_result))
+#define __compiler_offsetof(a, b)      __builtin_offsetof(a, b)
+
+/* Mark functions as cold. gcc will assume any path leading to a call
+   to them will be unlikely.  This means a lot of manual unlikely()s
+   are unnecessary now for any paths leading to the usual suspects
+   like BUG(), printk(), panic() etc. [but let's keep them for now for
+   older compilers]
+
+   Early snapshots of gcc 4.3 don't support this and we can't detect this
+   in the preprocessor, but we can live with this because they're unreleased.
+   Maketime probing would be overkill here.
+
+   gcc also has a __attribute__((__hot__)) to move hot functions into
+   a special section, but I don't see any sense in this right now in
+   the kernel context */
+#define __cold                 __attribute__((__cold__))
+
+#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
+
+#ifndef __CHECKER__
+# define __compiletime_warning(message) __attribute__((warning(message)))
+# define __compiletime_error(message) __attribute__((error(message)))
+#endif /* __CHECKER__ */
+
+/*
+ * Mark a position in code as unreachable.  This can be used to
+ * suppress control flow warnings after asm blocks that transfer
+ * control elsewhere.
+ *
+ * Early snapshots of gcc 4.5 don't support this and we can't detect
+ * this in the preprocessor, but we can live with this because they're
+ * unreleased.  Really, we need to have autoconf for the kernel.
+ */
+#define unreachable() __builtin_unreachable()
+
+/* Mark a function definition as prohibited from being cloned. */
+#define __noclone      __attribute__((__noclone__))
+
+/*
+ * Tell the optimizer that something else uses this function or variable.
+ */
+#define __visible __attribute__((externally_visible))
+
+/*
+ * GCC 'asm goto' miscompiles certain code sequences:
+ *
+ *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
+ *
+ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
+ *
+ * (asm goto is automatically volatile - the naming reflects this.)
+ */
+#define asm_volatile_goto(x...)        do { asm goto(x); asm (""); } while (0)
+
+#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
+#define __HAVE_BUILTIN_BSWAP32__
+#define __HAVE_BUILTIN_BSWAP64__
+#define __HAVE_BUILTIN_BSWAP16__
+#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
+
+#define KASAN_ABI_VERSION 4
diff --git a/version.m4 b/version.m4
index 7493e4f..5cae3c1 100644
--- a/version.m4
+++ b/version.m4
@@ -1,4 +1,4 @@
 m4_define([AC_PACKAGE_NAME],[GNU Mach])
-m4_define([AC_PACKAGE_VERSION],[1.4+git20150409])
+m4_define([AC_PACKAGE_VERSION],[1.4+git20150704])
 m4_define([AC_PACKAGE_BUGREPORT],address@hidden)
 m4_define([AC_PACKAGE_TARNAME],[gnumach])
diff --git a/vm/vm_fault.c b/vm/vm_fault.c
index 686156c..0fa4d6a 100644
--- a/vm/vm_fault.c
+++ b/vm/vm_fault.c
@@ -51,7 +51,7 @@
 #include <mach/memory_object.h>
 #include <vm/memory_object_user.user.h>
                                /* For memory_object_data_{request,unlock} */
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 #include <kern/slab.h>
 
 #if    MACH_PCSAMPLE
diff --git a/vm/vm_kern.c b/vm/vm_kern.c
index b997cb5..775d8e8 100644
--- a/vm/vm_kern.c
+++ b/vm/vm_kern.c
@@ -431,113 +431,13 @@ retry:
 }
 
 /*
- *     kmem_realloc:
- *
- *     Reallocate wired-down memory in the kernel's address map
- *     or a submap.  Newly allocated pages are not zeroed.
- *     This can only be used on regions allocated with kmem_alloc.
- *
- *     If successful, the pages in the old region are mapped twice.
- *     The old region is unchanged.  Use kmem_free to get rid of it.
- */
-kern_return_t kmem_realloc(
-       vm_map_t        map,
-       vm_offset_t     oldaddr,
-       vm_size_t       oldsize,
-       vm_offset_t     *newaddrp,
-       vm_size_t       newsize)
-{
-       vm_offset_t oldmin, oldmax;
-       vm_offset_t newaddr;
-       vm_object_t object;
-       vm_map_entry_t oldentry, newentry;
-       unsigned int attempts;
-       kern_return_t kr;
-
-       oldmin = trunc_page(oldaddr);
-       oldmax = round_page(oldaddr + oldsize);
-       oldsize = oldmax - oldmin;
-       newsize = round_page(newsize);
-
-       /*
-        *      Find space for the new region.
-        */
-
-       attempts = 0;
-
-retry:
-       vm_map_lock(map);
-       kr = vm_map_find_entry(map, &newaddr, newsize, (vm_offset_t) 0,
-                              VM_OBJECT_NULL, &newentry);
-       if (kr != KERN_SUCCESS) {
-               vm_map_unlock(map);
-
-               if (attempts == 0) {
-                       attempts++;
-                       slab_collect();
-                       goto retry;
-               }
-
-               printf_once("no more room for kmem_realloc in %p\n", map);
-               return kr;
-       }
-
-       /*
-        *      Find the VM object backing the old region.
-        */
-
-       if (!vm_map_lookup_entry(map, oldmin, &oldentry))
-               panic("kmem_realloc");
-       object = oldentry->object.vm_object;
-
-       /*
-        *      Increase the size of the object and
-        *      fill in the new region.
-        */
-
-       vm_object_reference(object);
-       vm_object_lock(object);
-       if (object->size != oldsize)
-               panic("kmem_realloc");
-       object->size = newsize;
-       vm_object_unlock(object);
-
-       newentry->object.vm_object = object;
-       newentry->offset = 0;
-
-       /*
-        *      Since we have not given out this address yet,
-        *      it is safe to unlock the map.  We are trusting
-        *      that nobody will play with either region.
-        */
-
-       vm_map_unlock(map);
-
-       /*
-        *      Remap the pages in the old region and
-        *      allocate more pages for the new region.
-        */
-
-       kmem_remap_pages(object, 0,
-                        newaddr, newaddr + oldsize,
-                        VM_PROT_DEFAULT);
-       kmem_alloc_pages(object, oldsize,
-                        newaddr + oldsize, newaddr + newsize,
-                        VM_PROT_DEFAULT);
-
-       *newaddrp = newaddr;
-       return KERN_SUCCESS;
-}
-
-/*
  *     kmem_alloc_wired:
  *
  *     Allocate wired-down memory in the kernel's address map
  *     or a submap.  The memory is not zero-filled.
  *
  *     The memory is allocated in the kernel_object.
- *     It may not be copied with vm_map_copy, and
- *     it may not be reallocated with kmem_realloc.
+ *     It may not be copied with vm_map_copy.
  */
 
 kern_return_t
@@ -661,7 +561,7 @@ retry:
                        goto retry;
                }
 
-               printf_once("no more rooom for kmem_alloc_aligned in %p\n", 
map);
+               printf_once("no more room for kmem_alloc_aligned in %p\n", map);
                return kr;
        }
 
diff --git a/vm/vm_kern.h b/vm/vm_kern.h
index 0869217..fb8ac7f 100644
--- a/vm/vm_kern.h
+++ b/vm/vm_kern.h
@@ -54,8 +54,6 @@ extern kern_return_t  kmem_alloc_pageable(vm_map_t, 
vm_offset_t *,
                                            vm_size_t);
 extern kern_return_t   kmem_alloc_wired(vm_map_t, vm_offset_t *, vm_size_t);
 extern kern_return_t   kmem_alloc_aligned(vm_map_t, vm_offset_t *, vm_size_t);
-extern kern_return_t   kmem_realloc(vm_map_t, vm_offset_t, vm_size_t,
-                                    vm_offset_t *, vm_size_t);
 extern void            kmem_free(vm_map_t, vm_offset_t, vm_size_t);
 
 extern void            kmem_submap(vm_map_t, vm_map_t, vm_offset_t *,
diff --git a/vm/vm_map.h b/vm/vm_map.h
index b8103eb..fc7730a 100644
--- a/vm/vm_map.h
+++ b/vm/vm_map.h
@@ -52,7 +52,7 @@
 #include <vm/vm_types.h>
 #include <kern/lock.h>
 #include <kern/rbtree.h>
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 
 /* TODO: make it dynamic */
 #define KENTRY_DATA_SIZE (256*PAGE_SIZE)
diff --git a/vm/vm_object.c b/vm/vm_object.c
index 71c0edb..8c6bbab 100644
--- a/vm/vm_object.c
+++ b/vm/vm_object.c
@@ -1336,16 +1336,6 @@ kern_return_t vm_object_copy_call(
        vm_page_t       p;
 
        /*
-        *      Set the backing object for the new
-        *      temporary object.
-        */
-
-       assert(src_object->ref_count > 0);
-       src_object->ref_count++;
-       vm_object_paging_begin(src_object);
-       vm_object_unlock(src_object);
-
-       /*
         *      Create a memory object port to be associated
         *      with this new vm_object.
         *
@@ -1358,10 +1348,18 @@ kern_return_t vm_object_copy_call(
         */
 
        new_memory_object = ipc_port_alloc_kernel();
-       if (new_memory_object == IP_NULL) {
-               panic("vm_object_copy_call: allocate memory object port");
-               /* XXX Shouldn't panic here. */
-       }
+       if (new_memory_object == IP_NULL)
+               return KERN_RESOURCE_SHORTAGE;
+
+       /*
+        *      Set the backing object for the new
+        *      temporary object.
+        */
+
+       assert(src_object->ref_count > 0);
+       src_object->ref_count++;
+       vm_object_paging_begin(src_object);
+       vm_object_unlock(src_object);
 
        /* we hold a naked receive right for new_memory_object */
        (void) ipc_port_make_send(new_memory_object);
diff --git a/vm/vm_object.h b/vm/vm_object.h
index 5c42f56..3bfc67a 100644
--- a/vm/vm_object.h
+++ b/vm/vm_object.h
@@ -45,7 +45,7 @@
 #include <kern/lock.h>
 #include <kern/assert.h>
 #include <kern/debug.h>
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 #include <vm/pmap.h>
 #include <ipc/ipc_types.h>
 
diff --git a/vm/vm_page.h b/vm/vm_page.h
index 4fe1b41..e6a8c49 100644
--- a/vm/vm_page.h
+++ b/vm/vm_page.h
@@ -42,7 +42,7 @@
 #include <kern/queue.h>
 #include <kern/lock.h>
 
-#include <kern/macro_help.h>
+#include <kern/macros.h>
 #include <kern/sched_prim.h>   /* definitions of wait/wakeup */
 
 #if    MACH_VM_DEBUG

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/gnumach.git



reply via email to

[Prev in Thread] Current Thread [Next in Thread]