diff -Npur gnumach.old/ChangeLog gnumach.new/ChangeLog
--- gnumach.old/ChangeLog	2006-04-02 07:48:52.000000000 -0300
+++ gnumach.new/ChangeLog	2006-04-05 23:38:30.000000000 -0300
@@ -1,3 +1,15 @@
+2006-04-05  Leonardo Lopes Pereira  <leonardolopespereira@gmail.com>
+
+	* i386/Makerules.in: Remove the definition of CONTINUATIONS.
+	* ipc/mach_msg.c: Adopt all users of CONTINUATIONS as if it were
+	always defined.
+	* kern/eventcount.c: Likewise.
+	* kern/ipc_sched.c: Likewise.
+	* kern/syscall_subr.c: Likewise.
+	* vm/vm_fault.c: Likewise.
+	* vm/vm_pageout.c: Likewise.
+	* vm/vm_resident.c: Likewise.
+
 2006-04-02  Thomas Schwinge  <tschwinge@gnu.org>
 
 	* Makerules.in (%_user.c, %_server.c): Those are `.PRECIOUS'.
diff -Npur gnumach.old/ChangeLog.~1.128.2.71.~ gnumach.new/ChangeLog.~1.128.2.71.~
--- gnumach.old/ChangeLog.~1.128.2.71.~	1969-12-31 21:00:00.000000000 -0300
+++ gnumach.new/ChangeLog.~1.128.2.71.~	2006-04-02 07:48:52.000000000 -0300
@@ -0,0 +1,3253 @@
+2006-04-02  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* Makerules.in (%_user.c, %_server.c): Those are `.PRECIOUS'.
+	(%.migs.d, %.migu.d): New targets.
+	(%.migs_d, %.migu_d, %.migsh_d, %.miguh_d): Remove targets.
+	Adopt the `include's to the renamed targets.
+	* Makefile.in (clean): Adopt to the renamed targets.
+	* i386/Makefile.in (clean): Likewise.
+
+	* i386/Makefile.in (boothdr.o): New target.
+
+2006-03-21  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* Makefile.in (clean): Also remove `kernel.gz', `kernel.stripped' and
+	`kernel.stripped.gz'.
+
+	* Makefile.in (kernel.o): Handle `$(systype)-objfiles-prepend'.
+	* i386/Makefile.in (sysdep.a): Likewise.
+	* i386/Makerules.in (kernel-objfiles-prepend): Transform variable into
+	`$(systype)-objfiles-prepend'.
+	(kernel.o): Remove target.
+
+2006-03-20  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* DEVELOPMENT: Document the NORMA removal.
+
+2006-03-20  Leonardo Lopes Pereira  <leonardolopespereira@gmail.com>
+
+	Remove unused and unsupported code.  Consult the file `DEVELOPMENT'
+	for details.
+
+	[patch #4982]
+	* bogus/norma_device.h: Remove file.
+	* bogus/norma_ether.h: Likewise.
+	* bogus/norma_ipc.h: Likewise.
+	* bogus/norma_task.h: Likewise.
+	* bogus/norma_vm.h: Likewise.
+	* include/mach/mach_norma.defs: Likewise.
+	* include/mach/norma_task.defs: Likewise.
+	* include/mach/norma_special_ports.h: Likewise.
+	* Makefile.in (bogus-files): Remove `norma_device.h', `norma_ether.h',
+	`norma_ipc.h', `norma_task.h' and `norma_vm.h'.
+	(mach-headers): Remove `mach_norma.defs', `norma_task.defs' and
+	`norma_special_ports.h'.
+	* device/ds_routines.c: Don't include <norma_device.h> anymore and
+	adopt all users of NORMA_DEVICE as if it were always defined to `0'.
+	* device/net_io.c: Likewise for <norma_ether.h>, NORMA_ETHER.
+	* kern/machine.c: Likewise.
+	* ddb/db_command.c: Likevise for <norma_ipc.h>, NORMA_IPC.
+	* ipc/ipc_init.c: Likewise.
+	* ipc/ipc_kmsg.c: Likewise.
+	* ipc/ipc_kmsg.h: Likewise.
+	* ipc/ipc_mqueue.c: Likewise.
+	* ipc/ipc_notify.c: Likewise.
+	* ipc/ipc_port.c: Likewise.
+	* ipc/ipc_port.h: Likewise.
+	* ipc/ipc_space.c: Likewise.
+	* ipc/ipc_space.h: Likewise.
+	* ipc/mach_msg.c: Likewise.
+	* kern/ast.c: Likewise.
+	* kern/debug.c: Likewise.
+	* kern/exception.c: Likewise.
+	* kern/startup.c: Likewise.
+	* vm/memory_object.c: Likewise.
+	* vm/vm_map.c: Likewise.
+	* kern/ipc_kobject.c: Likewise for <norma_task.h>, NORMA_TASK.
+	* kern/task.c: Likewise.
+	* kern/task.h: Likewise.
+	* ddb/db_command.c: Likewise for <norma_vm.h>, NORMA_VM.
+	* device/dev_pager.c: Likewise.
+	* include/mach/mach_types.defs: Likewise.
+	* include/mach/mach_types.h: Likewise.
+	* include/mach/memory_object_default.defs: Likewise.
+	* include/mach/memory_object.defs: Likewise.
+	* ipc/ipc_kmsg.c: Likewise.
+	* kern/ipc_kobject.c: Likewise.
+	* kern/ipc_mig.c: Likewise.
+	* kern/startup.c: Likewise.
+	* vm/memory_object.c: Likewise.
+	* vm/vm_object.c: Likewise.
+	* vm/vm_object.h: Likewise.
+	* vm/vm_pageout.c: Likewise.
+
+2006-03-19  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* DEVELOPMENT: Document the FIPC removal.
+
+2006-03-19  Leonardo Lopes Pereira  <leonardolopespereira@gmail.com>
+
+	Remove unused and unsupported code.  Consult the file `DEVELOPMENT'
+	for details.
+        
+	[patch #4982]
+	* ipc/fipc.c: Remove file.
+	* ipc/fipc.h: Likewise.
+	* Makefile.in (ipc-cfiles): Remove `fipc.c'.
+	(ipc-files): Remove `fipc.h'.
+	* device/device_init.c [FIPC]: Remove code.
+	* device/net_io.c [FIPC]: Likewise.
+	* include/mach/syscall_sw.h [FIPC]: Likewise.
+	* kern/syscall_sw.c [FIPC]: Likewise.
+
+2006-03-15  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* configure.in: Check for strip and gzip.
+	* configure: Regenerated.
+	* Makerules.in (GZIP, STRIP): New variables.
+	(%.gz, %.stripped): New targets.
+
+2006-03-04  Roland McGrath  <roland@frob.com>
+
+	* Makefile.in (DEFS): Substitute once and use the variable elsewhere.
+
+2006-03-04  Samuel Thibault  <samuel.thibault@ens-lyon.org>
+
+	[patch #4737]
+	* i386/i386/iopb.c: Include "vm_param.h".
+	(io_tss_init): Fix address and limit of user TSS.
+
+2006-03-04  Thomas Schwinge  <tschwinge@gnu.org>
+
+	Remove unused and unsupported code.  Consult the file
+	`DEVELOPMENT' for details.  Partly based on suggestions by
+	Gianluca Guida <glguida@gmail.com>.
+
+	* i386/bogus/par.h: Remove file.
+	* i386/i386at/if_par.c: Likewise.
+	* i386/i386at/if_par.h: Likewise.
+	* i386/i386at/conf.c: Don't include <par.h> anymore and adopt all users
+	of NPAR as if it were always defined to `0'.
+	* i386/i386at/lpr.c: Likewise.
+
+	* i386/bogus/de6c.h: Remove file.
+	* i386/i386at/if_de6c.c: Likewise.
+	* i386/i386at/if_de6c.h: Likewise.
+	* i386/i386at/if_de6s.S: Likewise.
+	* i386/i386at/conf.c: Don't include <de6c.h> anymore and adopt all
+	users of NDE6C as if it were always defined to `0'.
+	* i386/i386at/lpr.c: Likewise.
+
+2006-02-20  Thomas Schwinge  <tschwinge@gnu.org>
+
+	Remove unused and unsupported code.  Consult the file
+	`DEVELOPMENT' for details.  Partly based on suggestions by
+	Gianluca Guida <glguida@gmail.com>.
+
+	* i386/bogus/blit.h: Remove file.
+	* i386/i386at/blit.c: Likewise.
+	* i386/i386at/blitreg.h: Likewise.
+	* i386/i386at/blituser.h: Likewise.
+	* i386/i386at/blitvar.h: Likewise.
+	* i386/i386at/conf.c: Don't include <blit.h> anymore and adopt all
+	users of NBLIT as if it were always defined to `0'.
+	* i386/i386at/kd.c: Likewise.
+	(blit_init): Remove definition.
+	(blit_present): Likewise and adopt all users as if it were always
+	defined to `FALSE'.
+	* i386/Makefile.in (i386at-files): Remove `blit.c'.
+
+	* bogus/net_atm.h: Remove file.
+	* Makefile.in (bogus-files): Remove `net_atm.h'.
+	* kern/syscall_sw.c: Don't include <net_atm.h> anymore and adopt all
+	users of NET_ATM as if it were always defined to `0'.
+	* kern/task.c: Likewise.
+	* kern/task.h: Likewise.
+	* kern/thread.c: Likewise.
+	* kern/thread.h: Likewise.
+
+	* util/about_to_die.c: Remove file.
+	* util/config.h: Likewise.
+	* util/cpu.c: Likewise.
+	* util/cpu.h: Likewise.
+	* util/cpu_init.c: Likewise.
+	* util/cpu_subs.h: Likewise.
+	* util/debug.h: Likewise.
+	* util/die.c: Likewise.
+	* util/phys_mem.h: Likewise.
+	* util/ref_count.h: Likewise.
+	* util/cpus.h: Move from here...
+	* bogus/cpus.h: ... to here.
+	* Makefile.in (bogus-files): Add `cpus.h'.
+	(util-cfiles): Only contain `putchar.c' and `puts.c'.
+	(util-files): Only contain `$(util-cfiles)'.
+
+	* i386/util/NOTES: Remove file.
+	* i386/util/anno.c: Likewise.
+	* i386/util/anno.h: Likewise.
+	* i386/util/cpu.h: Likewise.
+	* i386/util/cpu_subs.h: Likewise.
+	* i386/util/cpu_tables_init.c: Likewise.
+	* i386/util/cpu_tables_load.c: Likewise.
+	* i386/util/crtn.S: Likewise.
+	* i386/util/debug.h: Likewise.
+	* i386/util/gdt.c: Likewise.
+	* i386/util/gdt.h: Likewise.
+	* i386/util/gdt_sels.h: Likewise.
+	* i386/util/i16/debug.h: Likewise.
+	* i386/util/i16/i16.h: Likewise.
+	* i386/util/i16/i16_die.c: Likewise.
+	* i386/util/i16/i16_gdt_init_temp.c: Likewise.
+	* i386/util/i16/i16_nanodelay.c: Likewise.
+	* i386/util/i16/i16_puts.c: Likewise.
+	* i386/util/i16/i16_writehex.c: Likewise.
+	* i386/util/i386_asm.sym: Likewise.
+	* i386/util/idt.c: Likewise.
+	* i386/util/idt.h: Likewise.
+	* i386/util/idt_inittab.S: Likewise.
+	* i386/util/idt_inittab.h: Likewise.
+	* i386/util/ldt.h: Likewise.
+	* i386/util/trap.h: Likewise.
+	* i386/util/trap_asm.sym: Likewise.
+	* i386/util/trap_dump.c: Likewise.
+	* i386/util/trap_dump_die.c: Likewise.
+	* i386/util/trap_handler.S: Likewise.
+	* i386/util/trap_return.S: Likewise.
+	* i386/util/tss.c: Likewise.
+	* i386/util/tss.h: Likewise.
+	* i386/util/tss_dump.c: Likewise.
+	* i386/util/vm_param.h: Likewise.
+
+	* i386/pc/NOTES: Remove file.
+	* i386/pc/debug.h: Likewise.
+	* i386/pc/exit.c: Likewise.
+	* i386/pc/gdt.h: Likewise.
+	* i386/pc/gdt_sels.h: Likewise.
+	* i386/pc/i16/i16_a20.c: Likewise.
+	* i386/pc/i16/i16_a20.h: Likewise.
+	* i386/pc/i16/i16_bios.h: Likewise.
+	* i386/pc/i16/i16_exit.c: Likewise.
+	* i386/pc/i16/i16_ext_mem.c: Likewise.
+	* i386/pc/i16/i16_init.c: Likewise.
+	* i386/pc/i16/i16_main.c: Likewise.
+	* i386/pc/i16/i16_pic.c: Likewise.
+	* i386/pc/i16/i16_putchar.c: Likewise.
+	* i386/pc/i16/i16_raw.c: Likewise.
+	* i386/pc/i16/i16_raw_test_a20.S: Likewise.
+	* i386/pc/i16/i16_real_int.S: Likewise.
+	* i386/pc/i16/i16_switch.h: Likewise.
+	* i386/pc/i16/phys_mem_collect.c: Likewise.
+	* i386/pc/i16/phys_mem_sources.h: Likewise.
+	* i386/pc/i16/raw_exit.c: Likewise.
+	* i386/pc/i16/raw_real_int.c: Likewise.
+	* i386/pc/ipl.h: Likewise.
+	* i386/pc/irq.h: Likewise.
+	* i386/pc/irq_list.h: Likewise.
+	* i386/pc/pc_asm.sym: Likewise.
+	* i386/pc/phys_mem.h: Likewise.
+	* i386/pc/phys_mem_add.c: Likewise.
+	* i386/pc/pic.c: Likewise.
+	* i386/pc/pic.h: Likewise.
+	* i386/pc/putchar.c: Likewise.
+	* i386/pc/real.h: Likewise.
+	* i386/pc/real_tss.c: Likewise.
+	* i386/pc/real_tss.h: Likewise.
+	* i386/pc/real_tss_def.S: Likewise.
+	* i386/pc/rv86/config.h: Likewise.
+	* i386/pc/rv86/gdt_sels.h: Likewise.
+	* i386/pc/rv86/idt_irq_init.c: Likewise.
+	* i386/pc/rv86/rv86_real_int.c: Likewise.
+	* i386/pc/rv86/rv86_real_int_asm.S: Likewise.
+	* i386/pc/rv86/rv86_reflect_irq.S: Likewise.
+	* i386/pc/rv86/rv86_trap_handler.S: Likewise.
+	* i386/pc/rv86/trap_handler.S: Likewise.
+
+	* i386/imps/Makefile.in: Remove file.
+	* i386/imps/apic.h: Likewise.
+	* i386/imps/cpu_number.h: Likewise.
+	* i386/imps/cpus.h: Likewise.
+	* i386/imps/imps.c: Likewise.
+	* i386/imps/impsasm.sym: Likewise.
+
+	* i386/dos/dos_buf.c: Remove file.
+	* i386/dos/dos_check_err.c: Likewise.
+	* i386/dos/dos_close.c: Likewise.
+	* i386/dos/dos_fstat.c: Likewise.
+	* i386/dos/dos_gettimeofday.c: Likewise.
+	* i386/dos/dos_io.h: Likewise.
+	* i386/dos/dos_open.c: Likewise.
+	* i386/dos/dos_read.c: Likewise.
+	* i386/dos/dos_rename.c: Likewise.
+	* i386/dos/dos_seek.c: Likewise.
+	* i386/dos/dos_tcgetattr.c: Likewise.
+	* i386/dos/dos_unlink.c: Likewise.
+	* i386/dos/dos_write.c: Likewise.
+	* i386/dos/i16/gdt.h: Likewise.
+	* i386/dos/i16/gdt_sels.h: Likewise.
+	* i386/dos/i16/i16_crt0.S: Likewise.
+	* i386/dos/i16/i16_crt0.h: Likewise.
+	* i386/dos/i16/i16_dos.h: Likewise.
+	* i386/dos/i16/i16_dos_mem.c: Likewise.
+	* i386/dos/i16/i16_exit.c: Likewise.
+	* i386/dos/i16/i16_main.c: Likewise.
+	* i386/dos/i16/i16_putchar.c: Likewise.
+	* i386/dos/i16/i16_vcpi.c: Likewise.
+	* i386/dos/i16/i16_xms.c: Likewise.
+	* i386/dos/i16/idt.h: Likewise.
+	* i386/dos/i16/phys_mem_sources.h: Likewise.
+	* i386/dos/putchar.c: Likewise.
+
+	* chips/atm.c: Remove file.
+	* chips/atmreg.h: Likewise.
+	* chips/audio.c: Likewise.
+	* chips/audio_config.h: Likewise.
+	* chips/audio_defs.h: Likewise.
+	* chips/bt431.c: Likewise.
+	* chips/bt431.h: Likewise.
+	* chips/bt455.c: Likewise.
+	* chips/bt455.h: Likewise.
+	* chips/bt459.c: Likewise.
+	* chips/bt459.h: Likewise.
+	* chips/bt478.c: Likewise.
+	* chips/bt478.h: Likewise.
+	* chips/build_font.c: Likewise.
+	* chips/cfb_hdw.c: Likewise.
+	* chips/cfb_misc.c: Likewise.
+	* chips/dc503.c: Likewise.
+	* chips/dc503.h: Likewise.
+	* chips/dtop.h: Likewise.
+	* chips/dtop_handlers.c: Likewise.
+	* chips/dtop_hdw.c: Likewise.
+	* chips/dz_7085.h: Likewise.
+	* chips/dz_defs.h: Likewise.
+	* chips/dz_hdw.c: Likewise.
+	* chips/eccreg.h: Likewise.
+	* chips/fb_hdw.c: Likewise.
+	* chips/fb_misc.c: Likewise.
+	* chips/fdc_82077.h: Likewise.
+	* chips/fdc_82077_hdw.c: Likewise.
+	* chips/frc.c: Likewise.
+	* chips/ims332.c: Likewise.
+	* chips/ims332.h: Likewise.
+	* chips/isdn_79c30.h: Likewise.
+	* chips/isdn_79c30_hdw.c: Likewise.
+	* chips/kernel_font.c: Likewise.
+	* chips/kernel_font.data: Likewise.
+	* chips/lance.c: Likewise.
+	* chips/lance.h: Likewise.
+	* chips/lance_mapped.c: Likewise.
+	* chips/lk201.c: Likewise.
+	* chips/lk201.h: Likewise.
+	* chips/mc_clock.c: Likewise.
+	* chips/mc_clock.h: Likewise.
+	* chips/mouse.c: Likewise.
+	* chips/nc.c: Likewise.
+	* chips/nc.h: Likewise.
+	* chips/nw.h: Likewise.
+	* chips/nw_mk.c: Likewise.
+	* chips/nw_mk.h: Likewise.
+	* chips/pm_defs.h: Likewise.
+	* chips/pm_hdw.c: Likewise.
+	* chips/pm_misc.c: Likewise.
+	* chips/scc_8530.h: Likewise.
+	* chips/scc_8530_hdw.c: Likewise.
+	* chips/screen.c: Likewise.
+	* chips/screen.h: Likewise.
+	* chips/screen_defs.h: Likewise.
+	* chips/screen_switch.c: Likewise.
+	* chips/screen_switch.h: Likewise.
+	* chips/serial_console.c: Likewise.
+	* chips/serial_defs.h: Likewise.
+	* chips/sfb_hdw.c: Likewise.
+	* chips/sfb_misc.c: Likewise.
+	* chips/spans.c: Likewise.
+	* chips/spans.h: Likewise.
+	* chips/tca100.c: Likewise.
+	* chips/tca100.h: Likewise.
+	* chips/tca100_if.c: Likewise.
+	* chips/tca100_if.h: Likewise.
+	* chips/vs42x_rb.h: Likewise.
+	* chips/xcfb_hdw.c: Likewise.
+	* chips/xcfb_misc.c: Likewise.
+	* chips/xcfb_monitor.h: Likewise.
+	* Makefile.in (chips-files): Only contain `busses.c' and `busses.h'.
+	* kern/syscall_sw.c: Don't include <chips/nw_mk.h> anymore.
+
+	* i386/i386at/asm_startup.h: Remove file.
+	* i386/i386at/phys_mem_grab_page.c: Likewise.
+	* i386/Makefile.in (i386at-files): Remove `phys_mem_grab_page.c'.
+
+	* i386/bogus/evc.h: Remove file.
+	* i386/i386at/kd.c: Don't include <evc.h> anymore and adopt all	users
+	of NEVC as if it were always defined to `0'.
+	(evc1init): Remove definition and adopt all users as if it were always
+	defined to `FALSE'.
+
+	* i386/bogus/nscsi.h: Remove file.
+	* i386/i386at/model_dep.c: Don't include <nscsi.h> anymore and adopt
+	all users of NSCSI as if it were always defined to `0'.
+	(use_all_mem): Don't define anymore and adopt all users as if it were
+	always defined to `1'.
+	(NBBY, NBPW, DMA_MAX): Remove macros.
+	(alloc_dma_mem): Remove function.
+
+	* i386/bogus/asc.h: Remove file.
+	* i386/bogus/aha.h: Likewise.
+	* i386/bogus/eaha.h: Likewise.
+	* i386/bogus/sbic.h: Likewise.
+	* i386/bogus/sci.h: Likewise.
+	* i386/bogus/sii.h: Likewise.
+	* i386/bogus/siop.h: Likewise.
+	* i386/i386at/eisa.h: Likewise.
+	* scsi/adapters/README: Likewise.
+	* scsi/adapters/scsi_33C93.h: Likewise.
+	* scsi/adapters/scsi_33C93_hdw.c: Likewise.
+	* scsi/adapters/scsi_5380.h: Likewise.
+	* scsi/adapters/scsi_5380_hdw.c: Likewise.
+	* scsi/adapters/scsi_53C700.h: Likewise.
+	* scsi/adapters/scsi_53C700_hdw.c: Likewise.
+	* scsi/adapters/scsi_53C94.h: Likewise.
+	* scsi/adapters/scsi_53C94_hdw.c: Likewise.
+	* scsi/adapters/scsi_7061.h: Likewise.
+	* scsi/adapters/scsi_7061_hdw.c: Likewise.
+	* scsi/adapters/scsi_89352.h: Likewise.
+	* scsi/adapters/scsi_89352_hdw.c: Likewise.
+	* scsi/adapters/scsi_aha15.h: Likewise.
+	* scsi/adapters/scsi_aha15_hdw.c: Likewise.
+	* scsi/adapters/scsi_aha17_hdw.c: Likewise.
+	* scsi/adapters/scsi_dma.h: Likewise.
+	* scsi/adapters/scsi_user_dma.c: Likewise.
+	* scsi/adapters/scsi_user_dma.h: Likewise.
+	* scsi/compat_30.h: Likewise.
+	* scsi/disk_label.c: Likewise.
+	* scsi/mapped_scsi.c: Likewise.
+	* scsi/mapped_scsi.h: Likewise.
+	* scsi/pc_scsi_label.c: Likewise.
+	* scsi/rz.c: Likewise.
+	* scsi/rz.h: Likewise.
+	* scsi/rz_audio.c: Likewise.
+	* scsi/rz_cpu.c: Likewise.
+	* scsi/rz_disk.c: Likewise.
+	* scsi/rz_disk_bbr.c: Likewise.
+	* scsi/rz_host.c: Likewise.
+	* scsi/rz_labels.h: Likewise.
+	* scsi/rz_tape.c: Likewise.
+	* scsi/scsi.c: Likewise.
+	* scsi/scsi.h: Likewise.
+	* scsi/scsi2.h: Likewise.
+	* scsi/scsi_alldevs.c: Likewise.
+	* scsi/scsi_comm.c: Likewise.
+	* scsi/scsi_cpu.c: Likewise.
+	* scsi/scsi_defs.h: Likewise.
+	* scsi/scsi_disk.c: Likewise.
+	* scsi/scsi_endian.h: Likewise.
+	* scsi/scsi_jukebox.c: Likewise.
+	* scsi/scsi_optical.c: Likewise.
+	* scsi/scsi_printer.c: Likewise.
+	* scsi/scsi_rom.c: Likewise.
+	* scsi/scsi_scanner.c: Likewise.
+	* scsi/scsi_tape.c: Likewise.
+	* scsi/scsi_worm.c: Likewise.
+	* i386/i386at/autoconf.c: Don't include <aha.h> and <eaha.h> anymore
+	and adopt all users of NAHA and NEAHA as if it were always defined to
+	`0'.
+	* i386/i386at/conf.c: Likewise.
+	* Makefile.in (scsi-files): Remove variable and all users of it.
+
+	* i386/bogus/wt.h: Remove file.
+	* i386/i386at/autoconf.c: Don't include <wt.h> anymore and adopt all
+	users of NWT as if it were always defined to `0'.
+	* i386/i386at/conf.c: Likewise.
+
+	* i386/bogus/hpp.h: Remove file.
+	* i386/bogus/ul.h: Likewise.
+	* i386/bogus/wd.h: Likewise.
+	* i386/i386at/gpl/if_hpp.c: Likewise.
+	* i386/i386at/gpl/if_ns.c: Likewise.
+	* i386/i386at/gpl/if_nsreg.h: Likewise.
+	* i386/i386at/gpl/if_ul.c: Likewise.
+	* i386/i386at/gpl/if_wd.c: Likewise.
+	* i386/i386at/autoconf.c: Don't include <hpp.h>, <ul.h> and <wd.h>
+	anymore and adopt all users of NHPP, NUL and NWD as if they were always
+	defined to `0'.
+	* i386/i386at/conf.c: Likewise.
+
+	* i386/bogus/at3c501.h: Remove file.
+	* i386/i386at/if_3c501.c: Likewise.
+	* i386/i386at/if_3c501.h: Likewise.
+	* i386/i386at/autoconf.c: Don't include <at3c501.h> anymore and adopt
+	all users of NAT3C501 as if it were always defined to `0'.
+	* i386/i386at/conf.c: Likewise.
+
+	* i386/bogus/ns8390.h: Remove file.
+	* i386/i386at/ds8390.h: Likewise.
+	* i386/i386at/if_3c503.h: Likewise.
+	* i386/i386at/if_ns8390.c: Likewise.
+	* i386/i386at/if_ns8390.h: Likewise.
+	* i386/i386at/if_wd8003.h: Likewise.
+	* i386/i386at/autoconf.c: Don't include <ns8390.h> anymore and adopt
+	all users of NNS8390 as if it were always defined to `0'.
+	* i386/i386at/conf.c: Likewise.
+
+	* i386/bogus/ne.h: Remove file.
+	* i386/i386at/if_ne.c: Likewise.
+	* i386/i386at/if_nereg.h: Likewise.
+	* i386/i386at/autoconf.c: Don't include <ne.h> anymore and adopt all
+	users of NNE as if it were always defined to `0'.
+	* i386/i386at/conf.c: Likewise.
+
+	* i386/bogus/pc586.h: Remove file.
+	* i386/i386at/i82586.h: Likewise.
+	* i386/i386at/if_pc586.c: Likewise.
+	* i386/i386at/if_pc586.h: Likewise.
+	* i386/i386at/autoconf.c: Don't include <pc586.h> anymore and adopt all
+	users of NPC586 as if it were always defined to `0'.
+	* i386/i386at/conf.c: Likewise.
+
+	* i386/bogus/fd.h: Remove file.
+	* i386/i386at/fd.c: Likewise.
+	* i386/i386at/fdreg.h: Likewise.
+	* i386/i386at/nfd.c: Likewise.
+	* i386/i386at/nfdreg.h: Likewise.
+	* i386/Makefile.in (i386at-files): Remove `fd.c'.
+	* i386/i386at/autoconf.c: Don't include <fd.h> anymore and adopt all
+	users of NFD as if it were always defined to `0'.
+	* i386/i386at/conf.c: Likewise.
+
+	* i386/bogus/hd.h: Remove file.
+	* i386/i386at/nhd.c: Likewise.
+	* i386/i386at/nhdreg.h: Likewise.
+	* i386/i386at/autoconf.c: Don't include <hd.h> anymore and adopt all
+	users of NHD as if it were always defined to `0'.
+	* i386/i386at/conf.c: Likewise.
+
+	* DEVELOPMENT: New file.
+
+2006-02-05  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* Makerules.in: Don't set no_deps to true if MAKECMDGOALS is empty.
+
+2006-02-03  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* Makerules.in: Set no_deps to true if we don't need the dependency
+	files.
+	* i386/linux/Makefile.in: Do care about linux-flags if no_deps is true;
+	reverting the change from 2006-01-31.
+
+	* Makefile.in: Include Makerules through top_builddir, so that it will
+	automatically be rebuilt if needed.
+
+	* Makerules.in (CFLAGS): Added -fno-strict-aliasing.
+	* i386/linux/Makefile.in (linux-gen-flags): Likewise.
+
+2006-02-02  Sergio Lopez  <koro@sinrega.org>
+
+	* linux/src/drivers/scsi/eata_pio.c (eata_pio_detect): Fix a
+	off-by-one error when probing.
+	* linux/src/drivers/scsi/eata_dma.c (eata_detect): Likewise.
+	* linux/dev/drivers/scsi/eata_dma.c (eata_detect): Likewise.
+
+	* linux/src/drivers/net/apricot.c (apricot_probe): Increase eth_addr
+	size to 8 so we do not trash the stack when reading from the io ports.
+
+2006-02-02  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* Makerules.in: Move a comment ...
+	* Makefile.in: ... here.
+
+2006-02-01  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* linux/dev/drivers/block/genhd.c (add_bsd_partition): Only define if
+	both MACH and CONFIG_BSD_DISKLABEL are defined.
+	Reported by Matheus Morais <matheus.morais@gmail.com>.
+
+2006-01-31  Thomas Schwinge  <tschwinge@gnu.org>
+
+	Cleanup of GNU Mach's build system.  The system dependent parts are now
+	handled by the respective Makefile and no longer by the top-level one.
+
+	* configure, i386/configure, i386/linux/configure, linux/configure:
+	Regenerated.
+
+	* Makefile.in: Various cleanups.
+	(mach/machine, mach_machine): Targets removed.
+	(AWK, CC, CFLAGS, CPPFLAGS, DEFINES, INCLUDES, INSTALL, INSTALL_DATA)
+	(INSTALL_PROGRAM, LD, MIG, MIGFLAGS, NM): Variables moved into
+	Makerules.in.
+	Do not include $(sysdep)/Makefrag anymore.
+	(all, check, clean, distclean, mostlyclean, maintainer-clean, install)
+	(install-headers, install-kernel): Recurse into the system dependent
+	subdirectory.
+	(check): Add a basic test using mbchk.
+	(clean, distclean): Be more explicit in what to delete.
+	($(systype)/%): New target.
+	(kernel.o): Incorporate the system dependent archive.
+	(installed-sysdep-headers-names, $(installed-sysdep-headers-names)):
+	Variable and target moved into the system dependent Makefile.in.
+	(install-headers, mkheaderdirs): Don't care for the system dependent
+	header files.
+	(%.symc, %.symc.o, %.h, %_user.c, %_interface.h, %_server.c): Targets
+	moved into Makerules.in.
+	Inclusion of dependency files: Likewise.
+	(%.migs_d, %.migu_d, %.migsh_d, %.miguh_d, make-deps, %.d): Likewise.
+	Include Makerules.
+	* Makerules.in: New file, mainly based on Makefile.in.
+	* configure.in: Do not substitute cross_compiling and not explicitly
+	substitute LDFLAGS.
+	Check for cpp, ranlib, ar and mbchk.
+	Care for the mach/machine symbolic link.
+	Add Makerules as a config file.
+	* i386/Makefile.in: Various cleanups.
+	Merge i386/Makefrag and the system dependent stuff from Makefile.in
+	into this file.
+	(all, check, install, install-headers, install-kernel): Recurse into
+	the system dependent subdirectory.
+	(sysdep.o): transformed to the new target sysdep.a.
+	(linux/linux.o): Target removed.
+	(clean, distclean): Be more explicit in what to delete.
+	(linux/%): New target.
+	(install-headers): Install the system dependent header files.
+	(mkheaderdirs): New target.
+	Include the top-level Makerules.
+	* i386/Makefrag: File removed.
+	* i386/Makerules.in: New file.
+	* i386/configure.in: Synchronize AC_INIT to the top-level definition.
+	Do not check for ld and make.
+	Add Makerules as a config file.
+	* i386/linux/Makefile.in: Various cleanups.
+	Replace linux-objs with objfiles.
+	(check, install, install-headers, install-kernel): New empty targets.
+	Don't care about linux-flags if no_deps is true.
+	Inclusion of dependency files removed and instead...
+	Include the top-level Makerules.
+	* i386/linux/Makerules.in: New file.
+	* i386/linux/configure.ac: Synchronize AC_INIT to the top-level
+	definition.
+	Do not check for gcc and ld.
+	Do not explicitly substitute LDFLAGS.
+	Add Makerules as a config file.
+	* linux/configure.in: Synchronize AC_INIT to the top-level definition.
+	Do not create directories using a dummy file.
+	* linux/dummy.in: File removed.
+
+	* ddb/db_access.h: Include <machine/vm_param.h> instead of
+	"vm_param.h".
+	* kern/bootstrap.c: Likewise.
+	* kern/thread.c: Likewise.
+	* vm/vm_kern.c: Likewise.
+	* vm/vm_object.c: Likewise.
+	* vm/vm_resident.c: Likewise.
+
+2006-01-26  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* config.guess: Updated from the canonical source.
+	* config.sub: Likewise.
+
+2006-01-26  Jeroen Dekkers  <jeroen@dekkers.cx>
+
+	* i386/i386/locore.S (trap_push_segs): Switch fs and gs to kernel
+	data segment too.
+	(syscall_entry_2): Likewise.
+	* i386/i386/user_ldt.c (i386_set_ldt): Always copy the master LDT
+	when there is no old user LDT.
+
+2006-01-26  Samuel Thibault  <samuel.thibault@ens-lyon.org>
+
+	* linux/dev/arch/i386/kernel/irq.c (linux_intr): Disable interrupts
+	if the driver requested it through request_irq().
+
+	* linux/dev/drivers/block/ide.c (read_intr): Set the IRQ handler before
+	issuing a request.
+	(write_intr): Likewise.
+	(multwrite_intr): Likewise.
+
+2006-01-26  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* i386/linux/Makefile.in: Automatically recreate the `Makefile'.
+
+2006-01-23  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* i386/linux/configure: Regenerated.
+
+	* i386/linux/configure.ac: Only add a AC_DRIVER_ALIAS if it really is a
+	alias.
+
+2006-01-22  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* doc/mach.texi (Configuration): Document the recently added drivers.
+	* i386/README-Drivers: Likewise.
+
+	* configure, i386/configure, i386/linux/configure, linux/configure,
+	i386/linux/device-drivers.h.in: Regenerated.
+
+	* linux/src/drivers/net/ne2k-pci.c: Resolve conflicts.
+
+2006-01-22  Guillem Jover  <guillem@hadrons.org>
+
+	* i386/linux/configure.ac: Renamed winbond-840 driver to winbond_840.
+	Enable the starfire, intel_gige and natsemi network drivers.  Remove
+	"CONFIG_" from cb_chim, starfire, sundance, winbond840, hamachi,
+	natsemi, myson803 and ns820 driver declarations.  Replace INTER_GIGE
+	with INTEL_GIGE.
+	* linux/dev/drivers/net/Space.c: Add conditional probes for natsemi,
+	ns820, winbond840, hamachi, sundance, starfire, myson803 and intel-gige
+	drivers.
+
+	* linux/src/include/asm-i386/cache.h: New file from linux 2.2.26.
+	* linux/dev/include/linux/malloc.h: Include <asm/cache.h>.
+
+	* linux/src/drivers/net/ns820.c (netsami_drv_id): Renamed to ...
+	(ns820_drv_id): ... this.  Fix all callers.
+	* linux/src/drivers/net/intel-gige.c
+	(skel_netdev_probe): Renamed to ...
+	(igige_probe): ... this.
+	* linux/dev/drivers/net/eepro100.c: Remove obsoleted file.
+	* linux/src/drivers/net/eepro100.c (pci_id_tbl): Add PCI ID's from
+	linux-2.6.14-rc4.
+
+2006-01-22  Alfred M. Szmidt  <ams@gnu.org>
+
+	* i386/linux/configure.ac: Added `pci-scan.o' to the network driver
+	class.  (ns820, myson803, sundance, winbond-840, hamachi): New drivers.
+	* i386/linux/Makefile.in (linux-net-files): Added `cb_shim.c',
+	`hamachi.c', `intel-gige.c', `myson803.c', `natsemi.c', `ns820.c',
+	`starfire.c', `sundance.c', `winbond-840.c' and `pci-scan.c'.
+
+	* linux/dev/include/linux/modversions.h: New file.
+
+	* linux/src/drivers/net/cb_shim.c, linux/src/drivers/net/hamachi.c,
+	linux/src/drivers/net/intel-gige.c, linux/src/drivers/net/myson803.c,
+	linux/src/drivers/net/natsemi.c, linux/src/drivers/net/ns820.c,
+	linux/src/drivers/net/starfire.c, linux/src/drivers/net/sundance.c,
+	linux/src/drivers/net/winbond-840.c,
+	linux/src/drivers/net/kern_compat.h, linux/src/drivers/net/pci-scan.c,
+	linux/src/drivers/net/pci-scan.h: New files from netdrivers 3.5 package
+	(http://www.scyld.com/network).
+
+	* linux/src/drivers/net/3c59x.c, linux/src/drivers/net/eepro100.c,
+	linux/src/drivers/net/epic100.c, linux/src/drivers/net/ne2k-pci.c,
+	linux/src/drivers/net/rtl8139.c, linux/src/drivers/net/tulip.c,
+	linux/src/drivers/net/via-rhine.c, linux/src/drivers/net/yellowfin.c:
+	Updated files from netdrivers 3.5 (http://www.scyld.com/network).
+
+2006-01-22  Thomas Schwinge  <tschwinge@gnu.org>
+
+	* linux/src/drivers/net/ne2k-pci.c (ne_block_input, ne_block_output):
+	Fix previous patch.
+
+2005-07-12  Guillem Jover  <guillem@hadrons.org>
+
+	* configure: Regenerated.
+	* i386/configure: Regenerated.
+
+	* Drivers.macros (AC_DRIVER_CLASS): Use AH_TEMPLATE.
+	(AC_DRIVER): Set the value for the AC_DEFINE and AC_DEFINE_UNQUOTED
+	to 1.
+
+	* aclocal.m4 (AC_PROG_CC_LOCAL, AC_PROG_CC_WORKS_LOCAL): Removed.
+	* version.m4: New file.
+	* Makefile.in: Use PACKAGE_VERSION, not VERSION.
+	* doc/Makefile.in: Likewise.
+	* version.c.in: Likewise. Use PACKAGE_NAME, not "GNUmach".
+	* i386/linux/Makefile.in (configure): Change its source to
+	configure.ac.
+
+	* aclocal.m4: Add missing quotations.
+	* Drivers.macros: Likewise.
+	* configure.in: Likewise. Include version.m4 and use PACKAGE and
+	VERSION m4 macros from it.
+	* i386/configure.in: Likewise.
+	(AC_INIT): Use new syntax and move source check to AC_CONFIG_SRCDIR.
+	* i386/linux/configure.ac: Likewise. Use m4_sinclude, not sinclude.
+	* linux/configure.in: Likewise.
+
+	* i386/configure.in: Update AC_DEFINE to the new three argument form.
+	* i386/linux/configure.ac: Move AC_DEFINE inside AC_ARG_ENABLE.
+
+	* configure.in: Use AC_CONFIG_LINKS, not AC_LINK_FILES.
+	* linux/configure.in: Likewise.
+
+	* i386/configure.in: Call AC_CONFIG_FILES and use the new form of
+	AC_OUTPUT.
+	* i386/linux/configure.ac: Likewise.
+	* linux/configure.in: Likewise
+
+	* configure.in: Use AS_HELP_STRING in AC_ARG_ENABLE help strings.
+	* Drivers.macros: Likewise.
+	* i386/configure.in: Likewise.
+	* i386/linux/configure.ac: Likewise.
+
+2005-07-12  Neal H. Walfield  <neal@cs.uml.edu>
+
+	* configure.in: Update to use autoconf 2.57.
+	Do not error out if host_os is not GNU.
+	Update AC_DEFINEs to the required three argument form.
+	Don't call AC_CHECK_TOOL(CC, gcc) and AC_PROG_CC_LOCAL, just use
+	AC_PROG_CC.
+	AC_SUBST(LDFLAGS).
+	Refactor AC_CONFIG_SUBDIRS to not do variable substitution.
+	Call AC_CONFIG_FILES and use the new form of AC_OUTPUT.
+	* i386/configure.in: Require autoconf 2.57.
+	* linux/configure.in: Likewise.
+	* i386/linux/Drivers.in: Move from here...
+	* i386/linux/configure.ac: ... to here to conform to the
+	environment autoreconf expects.
+	(hurd_host_CPU): New macro.
+	Call AC_PROG_CC, not AC_PROG_CC_LOCAL.
+	AC_SUBST(LD_FLAGS).
+	(flashpoint): Update AC_DEFINE to the new three argument form.
+	* Drivers.macros (AC_DRIVER): Update AC_DEFINE to the new three
+	argument form.
+
+2005-05-24  Alfred M. Szmidt  <ams@gnu.org>
+
+	* i386/include/mach/i386/asm.h (END): New macro.
+
+	* i386/include/mach/i386/syscall_sw.h (kernel_trap): Call END.
+
+2005-05-28  Alfred M. Szmidt  <ams@gnu.org>
+
+	* linux/src/drivers/scsi/u14-34f.c (ihdlr): Silence gcc 4.x
+	errors.
+	* linux/src/drivers/scsi/qlogicisp.h: Likewise.
+	* linux/src/drivers/scsi/advansys.c: Likewise.
+	(advansys_reset, advansys_interrupt, asc_scsi_done_list,
+	(asc_enqueue, asc_dequeue, asc_dequeue_list, asc_rmqueue,
+	(asc_isqueued): Likewise.
+	* linux/src/drivers/scsi/53c78xx.c (NCR53c7xx_queue_command):
+	Likewise.
+	* linux/src/drivers/net/ne2k-pci.c (ne_block_input)
+	(ne_block_output): Likewise.
+	* linux/src/drivers/net/hp100.c (__initfunc): Likewise.
+	* linux/src/drivers/net/3c507.c (el16_interrupt): Likewise.
+	* linux/dev/drivers/scsi/seagate.c (seagate_st0x_queue_command):
+	Likewise.
+
+2005-05-26  Alfred M. Szmidt  <ams@gnu.org>
+
+	* device/cons.h (cn_tab) [KERNEL]: Removed extern declaration.
+
+	* linux/dev/include/linux/fs.h (super_blocks): Declare as an
+	pointer.
+
+2005-02-10  Guillem Jover  <guillem@hadrons.org>
+
+	* linux/dev/glue/block.c (rdwr_partial): Remove leftover assert.
+
+2005-01-22  Guillem Jover  <guillem@hadrons.org>
+
+	* linux/dev/include/linux/skbuff.h (skb_put, skb_push): Fix errors
+	for deprecated use of labels at end of compound statements.
+	* i386/i386/fpe_linkage.c (enable_fpe): Declare prototype.
+
+2005-01-22  Guillem Jover  <guillem@hadrons.org>
+
+	* linux/src/drivers/scsi/qlogicisp_asm.c: Remove file with binary
+	only firmware.
+	* linux/src/drivers/scsi/qlogicisp.c: Do not include "qlogicisp_asm.c".
+	(RELOAD_FIRMWARE): Set to 0.
+	(risc_code_addr01): New variable from qlogicisp_asm.c.
+	* linux/Files: Remove linux/src/drivers/scsi/qlogicisp_asm.c.
+
+2004-09-08  Neal H. Walfield  <neal@cs.uml.edu>
+
+	* linux/dev/kernel/printk.c: Include <kern/assert.h>.
+	(printk): Use vsnprintf, not linux_vsprintf to avoid buffer
+	overruns.
+
+	* kern/printf.c (struct vsnprintf_cookie): New structure.
+	(snputc): New function.
+	(vsnprintf): Likewise.
+
+2004-11-22  Guillem Jover  <guillem@hadrons.org>
+
+	* bogus/mach_assert.h: Change #ifdef DEBUG to #ifndef NDEBUG
+	for assert et al.
+	* kern/assert.h: Likewise.
+	* kern/debug.h: Likewise.
+	* util/debug.h: Likewise.
+
+	* i386/i386/debug.h: Move dump_ss definition out of [DEBUG].
+	* linux/dev/glue/block.c (rdwr_full): Remove invalid assert.
+
+2004-09-07  Neal H. Walfield  <neal@cs.uml.edu>
+
+	* linux/dev/glue/block.c (__brelse): Unconditionally kfree BH.
+	(getblk): Unconditionally kalloc BH.
+
+	* kern/kalloc.c [!NDEBUG] (kalloc_init_called): New static
+	variable.
+	(kalloc_init): Assert that kalloc_init_called is zero.
+	[! NDEBUG] Set kalloc_init_called to 1 on success.
+	(kalloc): Assert that kalloc_init_called is non-zero.
+	(kget): Likewise.
+	(kfree): Likewise.
+
+2004-11-22  Guillem Jover  <guillem@hadrons.org>
+
+	* i386/i386/locore.S (discover_x86_cpu_type): Enable function.
+	Enable ID flag for Cyrix CPU. Use %ebp to save the stack pointer.
+	Restore EFLAGS just after its last usage.
+	* i386/i386at/model_dep.c (c_boot_entry): Enable use of
+	discover_x86_cpu_type. Remove hardcoded cpu_type assignment.
+	* i386/include/mach/i386/eflags.h
+	(EFL_VI, EFL_VIP): New bits.
+	(EFL_AC, EFL_ID): Bits finally added.
+
+2004-10-26  Guillem Jover  <guillem@hadrons.org>
+
+	* i386/i386/fpe.b: Remove binary without source.
+	* i386/i386/fpe.b_elf: Likewise.
+	* i386/i386/fpe_linkage.c: Disable the code if [! FPE].
+	* i386/bogus/fpe.h: Add comment about not having an fpe implementation.
+	* i386/Makefrag (objfiles): Do not add fpe.o.
+	Remove targets to generate fpe.o.
+
+2004-02-29  Marcus Brinkmann  <marcus@gnu.org>
+
+	* NEWS: Add things that changed so far since 1.3.
+
+2004-02-02  Marco Gerards  <metgerards@student.han.nl>
+
+	* i386/i386at/kd.c (kdinit): Initialize the input buffer.
+
+	* i386/i386at/kd.h (KDSETLEDS): New macro.
+	* i386/i386at/kd_event.c (kbdsetstat): Handle KDSETLEDS here to
+	set the keyboard LEDs state.
+
+2004-01-19  Marco Gerards  <metgerards@student.han.nl>
+
+        * linux/dev/glue/block.c (init_partition): Don't check for BSD
+        partitions if the DOS partition is too small.
+
+2004-01-16  Marco Gerards  <metgerards@student.han.nl>
+
+	* linux/dev/glue/block.c (device_get_status): Correctly calculate
+	the number of blocks.
+
+2004-01-15  Alfred M. Szmidt  <ams@kemisten.nu>
+
+	* linux/dev/include/asm-i386/string.h (memscan): Don't use
+	multi-line string literals for asm().
+	* linux/dev/include/asm-i386/segment.h (__generic_memcpy_tofs)
+	(__generic_memcpy_fromfs): Likewise.
+	* linux/src/include/asm-i386/floppy.h (floppy_hardint): Likewise.
+	* i386/i386/proc_reg.h (flush_instr_queue): Likewise.
+	* i386/i386/gdt.c (gdt_init): Likewise.
+
+	* linux/src/drivers/scsi/aic7xxx.c: Updated from Linux 2.0.39
+	* linux/src/drivers/scsi/aic7xxx.h: Likewise.
+	* linux/src/drivers/scsi/aic7xxx_proc.c: Likewise.
+	* linux/src/drivers/scsi/scsicam.c: Likewise.
+	* linux/src/include/linux/pci.h: Likewise.
+
+	* linux/src/drivers/scsi/53c7,8xx.h (patch_dsa_32): Don't use
+	token paste operator (##).
+
+	* Makefile.in (kernel-undef): Match new output format from
+	nm (binutils) 2.14.x.
+
+2002-05-27  Roland McGrath  <roland@frob.com>
+
+	* Version 1.3 released.
+
+2002-05-23  Marcus Brinkmann  <marcus@gnu.org>
+
+	* i386/i386at/model_dep.c: Include <kern/cpu_number.h> and
+	<kern/assert.h>.
+	(machine_idle): New function.
+	* bogus/power_save.h (POWER_SAVE): Define to 1.
+
+2002-05-22  Roland McGrath  <roland@frob.com>
+
+	* configure.in (VERSION): New substituted variable: set to 1.3 now.
+	(version.c): Add it to AC_OUTPUT.
+	* configure: Regenerated.
+	* Makefile.in (version): New variable, set from that.
+	Remove vpath directive for version.c, not found in build dir.
+	(topfiles): version.c -> version.c.in
+	* doc/Makefile.in (mach-version): Substituted instead of constant.
+	* version.c: File removed, replaced with ...
+	* version.c.in: ... this new file.
+	(version): Make it const.  Use @VERSION@ for the number.
+
+	* Makefile.in (debian-files): Add postinst and prerm.
+	(dist): Use gzip -9 instead of tar z.
+
+	* linux/Files: Add missing files to the list:
+		linux/dev/drivers/net/eepro100.c
+		linux/src/include/asm-i386/hardirq.h
+		linux/src/include/asm-i386/spinlock.h
+		linux/src/include/linux/compatmac.h
+		linux/src/include/linux/spinlock.h
+
+	* linux/src/drivers/net/eth16i.c (eth16i_check_signature): Fix syntax:
+	#ifdef 0 -> #if 0
+
+	* Makefile.in (%.migs_d, %.migu_d): Fix sed substitution to match
+	whatever target file name gcc comes up with.
+	(%.migs_d, %.migu_d, %.symc.o, %_user.c, %_server.c):
+	Depend on $(before-compile).
+
+2002-04-24  Marcus Brinkmann  <marcus@gnu.org>
+
+	* debian/rules (DOCDIR): Move to
+	$(PREFIX)/share/doc/$(package-dev).
+
+2002-04-23  Roland McGrath  <roland@frob.com>
+
+	* i386/i386/ldt.c (ldt_init): Fix fencepost error in segment limits.
+
+2002-04-19  Roland McGrath  <roland@frob.com>
+
+	* gensym.awk: Emit \n\ at the end of lines inside strings.
+	* Makefile.in (%.symc: %.sym): Depend on gensym.awk.
+
+2002-03-29  Marcus Brinkmann  <marcus@g10code.de>
+
+	* doc/mach.texi: End index entry with full stop.
+
+2002-03-05  Roland McGrath  <roland@frob.com>
+
+	* kern/bootstrap.c: Include <alloca.h>.
+
+2002-03-04  Roland McGrath  <roland@frob.com>
+
+	* Makefile.in (%_interface.h %_server.c: %.srv): Pass -sheader switch
+	to mig, not -header.
+
+2001-11-23  Roland McGrath  <roland@frob.com>
+
+	* i386/i386at/i386at_ds_routines.c (device_deallocate): Do nothing if
+	argument is DEVICE_NULL.
+
+2001-10-21  Marcus Brinkmann  <marcus@gnu.org>
+
+	* linux/src/arch/i386/lib/delay.c: Convert HTML entities.
+	Reported by John Tobey <jtobey@john-edwin-tobey.org>.
+
+2001-10-13  Marcus Brinkmann  <marcus@gnu.org>
+
+	* debian/changelog: Update for next release.
+
+2001-10-07  Roland McGrath  <roland@frob.com>
+
+	* ddb/db_access.c: Fix obsolescent #else/#endif syntax.
+	* device/dev_name.c: Likewise.
+	* device/dev_pager.c: Likewise.
+	* device/ds_routines.c: Likewise.
+	* i386/i386/i386asm.sym: Likewise.
+	* include/device/device_reply.defs: Likewise.
+	* include/mach/memory_object.defs: Likewise.
+	* include/mach/memory_object_default.defs: Likewise.
+
+	* i386/i386/locore.S: Fix sloppy asm syntax to avoid warnings from
+	newer assembler (%ecx -> %cl in byte insns).
+
+	* kern/bootstrap.c (bootstrap_create): Fix inverted test logic for
+	compatibility case.  Ignore trailing newlines after space for
+	compatibility detection.
+	Reported by Neal H Walfield <neal@cs.uml.edu>.
+
+2001-10-06  Marcus Brinkmann  <marcus@gnu.org>
+
+	* README: Replace `GNU mach' by `GNU Mach', and remove
+	obsolete paragraph about kmsg device.
+
+2001-10-06  Marcus Brinkmann  <marcus@gnu.org>
+
+	* doc/mach.texi: Fix direntry.
+
+2001-10-05  Marcus Brinkmann  <marcus@gnu.org>
+
+	* doc/mach.texi: Replace `path name' by `file name' in one place.
+	Replace `illegal' by `invalid' and `to to' by `to' everwhere.
+
+	* debian/changelog: Prepare for next release.
+
+2001-10-04  Marcus Brinkmann  <marcus@gnu.org>
+
+	* doc: New directory.
+	* doc/Makefile.in: New file.
+	* doc/gpl.texi: Likewise.
+	* doc/fdl.texi: Likewise.
+	* doc/mach.texi: Likewise.
+	* configure.in: Add doc/Makefile to AC_OUTPUT call.
+	* configure: Regenerated.
+
+	* Makefile.in (dist): Create directories doc and debian.
+	(doc-files): New variable with documentation files.
+	(debian-files): New variable with Debian packaging files.
+
+	* debian/rules (stamp-build): Build documentation.
+	(build-gnumach): Install the documentation into the gnumach
+	package.
+	* debian/postrm: New file to install info document.
+	* debian/prerm: New file to install info document.
+
+2001-10-01  Marcus Brinkmann  <marcus@gnu.org>
+
+	* i386/i386/locore.S (tenmicrosec): Remove subroutine.
+	* i386/i386/pit.c (delaycount): Remove global variable.
+	(microdata): Likewise.
+	(clkstart): Do not call findspeed() and microfind().
+	(findspeed): Remove function.
+	(spinwait): Likewise.
+	(microfind): Likewise.  This function triggers a division by zero
+	trap on AMD K6 350Mhz+ and Athlon 1.1GHz+ machines (and in general
+	leads to bad results on fast cpus), and nothing uses this code anymore.
+
+2001-09-30  Roland McGrath  <roland@frob.com>
+
+	* kern/bootstrap.c (bootstrap_create): Ignore trailing spaces when
+	checking boot module string for containing none.
+
+2001-09-18  Marcus Brinkmann  <marcus@gnu.org>
+
+	* linux/dev/glue/misc.c: Do not include <linux/types.h> and
+	<linux/string.h>.
+	Remove global variable ___strtok.
+	Remove implementation of strspn, strpbrk, strtok and strstr.
+	* Makefile.in: Add strpbrk and strtok.
+
+2001-08-24  Roland McGrath  <roland@frob.com>
+
+	* kern/bootstrap.c (bootstrap_create): Make setting of boot-args and
+	root-device no longer conditional on [! OSKIT_MACH].
+	(bootstrap_create) [! OSKIT_MACH]: Parse FOO=BAR words out of the
+	multiboot command line and turn those into boot script variables.
+
+	* Makefile.in (clib-routines): Add strsep.
+	* kern/strings.h (strsep, strchr): Declare them.
+
+2001-08-23  Roland McGrath  <roland@frob.com>
+
+	* kern/bootstrap.c (bootstrap_create, user_bootstrap,
+	boot_script_exec_cmd, boot_script_task_resume): Add printfs at
+	various stages of startup.
+
+2001-08-21  Roland McGrath  <roland@frob.com>
+
+	* i386/i386at/model_dep.c (use_all_mem): Turn variable into macro.
+	(init_alloc_aligned): Make this function static.
+	Initially skip memory < 16MB and then wrap around to get it last.
+
+2001-08-20  Roland McGrath  <roland@frob.com>
+
+	Support "boot script" functionality in multiboot module strings.
+	* kern/bootstrap.c: Rewrite merged from oskit-branch.
+	* kern/boot_script.c, kern/boot_script.h: New files,
+	copied from boot/ directory in Hurd sources.
+	* Makefile.in (kern-cfiles): Add boot_script.c here.
+	(kern-files): Add boot_script.h here.
+	* NEWS: Mention the new feature.
+
+2001-08-18  Roland McGrath  <roland@frob.com>
+
+	* i386/i386at/model_dep.c (boot_info): Define a struct, not a pointer.
+	(c_boot_entry): Copy the contents into it rather than setting the ptr.
+	(c_boot_entry, init_alloc_aligned, pmap_valid_page, mem_size_init):
+	Update uses.
+	(init_alloc_aligned): Don't need to skip the boot_info memory.
+	* kern/bootstrap.c (boot_info): Update decl.
+	(bootstrap_create): Update uses.
+
+2001-08-18  Marcus Brinkmann  <marcus@gnu.org>
+
+	* linux/src/drivers/net/eepro100.c: File updated to version in
+	Linux 2.2.19.  This time for real.
+
+2001-08-18  Marcus Brinkmann  <marcus@gnu.org>
+
+	* debian/changelog: Update for next package upload.
+	* debian/control: Add gnumach-dbg package.
+	* debian/rules: New targets to build gnumach-dbg package.
+	Fix various bugs.
+
+2001-08-18  Marcus Brinkmann  <marcus@gnu.org>
+
+	* i386/i386at/kd.c (kdintr): In event mode, make it so that
+	0xE0 scancodes are received.
+	From Kalle Olavi Niemitalo <tosi@ees2.oulu.fi>.
+
+	* i386/i386at/kd.h: New constants KAX_REVERSE, KAX_UNDERLINE,
+	KAX_BLINK, KAX_BOLD, KAX_DIM, KAX_INVISIBLE, KAX_COL_UNDERLINE,
+	KAX_COL_DIM.
+	* i386/i386at/kd.c: Increase K_MAXESC to 32.
+	New global variable color_table to map color values.
+	New globals kd_color and kd_attrflags.
+	(kdinit): Initialize these variables.
+	(kd_update_kd_attr): New function.
+	(kd_parserest): Redone to support more terminal attributes,
+	including colors.
+
+2001-08-18  Marcus Brinkmann  <marcus@gnu.org>
+
+	* linux/src/drivers/net/eepro100.c: File updated to version in
+	Linux 2.2.19.
+	* linux/src/include/asm-i386/spinlock.h: New file from Linux 2.2.19.
+	* linux/src/include/asm-i386/hardirq.h: Likewise.
+	* linux/src/include/linux/spinlock.h: Likewise.
+	* linux/src/include/linux/compatmac.h: Likewise.
+        * linux/dev/drivers/net/eepro100.c: New file, modified version from
+        the above to glue it in gnumach.
+        Submitted by Kapil H. Paranjape <kapil@imsc.ernet.in>.
+
+2001-08-17  Roland McGrath  <roland@frob.com>
+
+	* Makefile.in (clib-routines): Add strchr.
+	(kernel-undef-bad): Depend on Makefile.
+
+	* Makefile.in ($(srcdir)/configure, $(srcdir)/config.h.in):
+	Use $(srcdir) in deps.
+	(Makefile, config.h, config.status): Likewise.
+
+2001-07-29  Marcus Brinkmann  <marcus@gnu.org>
+
+	* NEWS: Add items for this and other changes.
+	* configure.in: Define MACH_KMSG by default and document this in
+	the help output.
+	* configure: Regenerated.
+	* debian/rules: Do not enable kmsg explicitely.
+
+2001-07-18  Marcus Brinkmann  <marcus@gnu.org>
+
+	* debian/rules: Add -isp to dpkg-gencontrol invocation.
+	Move documentation to /share/doc.
+	* debian/changelog: Update.
+
+2001-06-28  Marcus Brinkmann  <marcus@gnu.org>
+
+	* linux/dev/drivers/block/ide.c (lba_capacity_is_ok): Do not
+	attempt to correct id->cyls, it is a short and for large disks the
+	number of cylinders necessary would not fit.  Subsequent checks
+	for lba support would fail.
+	(current_capacity): Likewise for drive->cyl.
+	(do_identify): Store value returned by current_capacity in
+	CAPACITY.  The check which corrects the number of bios cylinders
+	is not aggressive enough.  Update it with the check in linux
+	kernel-2.2.19.
+
+2001-06-25  Marcus Brinkmann  <marcus@gnu.org>
+
+	* i386/bogus/fpe.h (FPE): Define FPE to 0, as the floating point
+	emulation is broken anyway and blows up plex86.
+
+2001-06-17  Marcus Brinkmann  <marcus@gnu.org>
+
+	* debian/rules: Update to current version.
+
+2001-06-13  Roland McGrath  <roland@frob.com>
+
+	* linux/dev/glue/block.c (device_get_status: DEV_GET_RECORDS):
+	Always return 512 for DEV_GET_SIZE_RECORD_SIZE as DEV_GET_SIZE does.
+
+2001-05-27  Marcus Brinkmann  <marcus@gnu.org>
+
+	* debian/rules: Add --enable-ncr53c8xx to configure.
+
+1999-10-06  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* linux/src/drivers/scsi/tmscsiw.c: Removed.
+	* linux/src/drivers/scsi/tmscsiw.h: Likewise.
+	* linux/src/drivers/scsi/dc390w.h: Likewise.
+	* i386/linux/device-drivers.h.in (CONFIG_SCSI_DC390W): Deleted.
+	* i386/linux/Drivers.in: Remove linux_DRIVER(dc390w, ...). Now
+	dc390w, dc390u, and dc390f are aliases to ncr53c8xx.
+	* i386/linux/configure: Regenerated.
+	* linux/Files: Likewise.
+	* i386/linux/Makefile.in (linux-scsi-files): Delete tmscsiw.c.
+	* linux/dev/drivers/scsi/hosts.c: Do not include dc390w.h.
+	Reported by Andreas Voegele <andreas.voegele@nikocity.de>.
+
+2001-05-20  Roland McGrath  <roland@frob.com>
+
+	* kern/sched_prim.c (state_panic): New function, panic with some
+	info when a thread's state is bogus.
+	(thread_wakeup_prim): Use that instead of uninformative panic.
+	(thread_invoke): Likewise.
+	(thread_dispatch): Likewise.
+
+2001-05-12  Marcus Brinkmann  <marcus@gnu.org>
+
+	* ipc/ipc_object.c (ipc_object_alloc): Remove initialization of
+	*namep, which was without effect.
+
+2001-04-29  Marcus Brinkmann  <marcus@gnu.org>
+
+	* debian/changelog: New entries for past Debian uploads.
+	* debian/rules: Disable eatdma driver (breaks AMD K7), do
+	not enable com, lpr (com is redundant, lpr doesn't work),
+	move enabling of kmsg in its own line.
+	* debian/control: Add build dependency on mig and sharutils.
+
+2001-04-29  Marcus Brinkmann  <marcus@gnu.org>
+
+	* device/chario.c: Set number of elements of tthiwat and ttlowat
+	to NSPEEDS rather than 16. Initialize the two new elements.
+	(chario_init): Initialize pdma_timeouts and pdma_water_mark for
+	B57600 and B115200.
+
+2001-04-27  Marcus Brinkmann  <marcus@gnu.org>
+
+	* include/device/tty_status.h: New macros B57600 and B115200,
+	increase NSPEED accordingly.
+	* i386/i386at/com.c (divisorreg): New divisor 1.
+
+2001-04-04  Roland McGrath  <roland@frob.com>
+
+	* ddb/db_access.h: Fix obsolescent #else/#endif syntax.
+	* ddb/db_aout.c: Likewise.
+	* ddb/db_break.c: Likewise.
+	* ddb/db_break.h: Likewise.
+	* ddb/db_command.c: Likewise.
+	* ddb/db_command.h: Likewise.
+	* ddb/db_cond.c: Likewise.
+	* ddb/db_examine.c: Likewise.
+	* ddb/db_expr.c: Likewise.
+	* ddb/db_ext_symtab.c: Likewise.
+	* ddb/db_input.c: Likewise.
+	* ddb/db_lex.c: Likewise.
+	* ddb/db_macro.c: Likewise.
+	* ddb/db_mp.c: Likewise.
+	* ddb/db_output.c: Likewise.
+	* ddb/db_print.c: Likewise.
+	* ddb/db_run.c: Likewise.
+	* ddb/db_sym.c: Likewise.
+	* ddb/db_task_thread.c: Likewise.
+	* ddb/db_task_thread.h: Likewise.
+	* ddb/db_trap.c: Likewise.
+	* ddb/db_variables.c: Likewise.
+	* ddb/db_watch.c: Likewise.
+	* ddb/db_watch.h: Likewise.
+	* ddb/db_write_cmd.c: Likewise.
+	* device/dev_pager.c: Likewise.
+	* device/device_port.h: Likewise.
+	* device/device_types_kernel.h: Likewise.
+	* device/ds_routines.h: Likewise.
+	* device/errno.h: Likewise.
+	* device/if_ether.h: Likewise.
+	* device/if_hdr.h: Likewise.
+	* device/io_req.h: Likewise.
+	* device/net_io.c: Likewise.
+	* device/net_io.h: Likewise.
+	* i386/i386/ast_check.c: Likewise.
+	* i386/i386/cswitch.S: Likewise.
+	* i386/i386/db_disasm.c: Likewise.
+	* i386/i386/db_interface.c: Likewise.
+	* i386/i386/db_trace.c: Likewise.
+	* i386/i386/debug.h: Likewise.
+	* i386/i386/debug_i386.c: Likewise.
+	* i386/i386/debug_trace.S: Likewise.
+	* i386/i386/eflags.h: Likewise.
+	* i386/i386/gdt.h: Likewise.
+	* i386/i386/hardclock.c: Likewise.
+	* i386/i386/idt-gen.h: Likewise.
+	* i386/i386/ipl.h: Likewise.
+	* i386/i386/ktss.h: Likewise.
+	* i386/i386/kttd_interface.c: Likewise.
+	* i386/i386/ldt.h: Likewise.
+	* i386/i386/lock.h: Likewise.
+	* i386/i386/locore.S: Likewise.
+	* i386/i386/mp_desc.h: Likewise.
+	* i386/i386/pic.c: Likewise.
+	* i386/i386/pic.h: Likewise.
+	* i386/i386/pio.h: Likewise.
+	* i386/i386/pit.h: Likewise.
+	* i386/i386/seg.h: Likewise.
+	* i386/i386/thread.h: Likewise.
+	* i386/i386/trap.c: Likewise.
+	* i386/i386/trap.h: Likewise.
+	* i386/i386/vm_param.h: Likewise.
+	* i386/i386/vm_tuning.h: Likewise.
+	* i386/i386at/autoconf.c: Likewise.
+	* i386/i386at/blit.c: Likewise.
+	* i386/i386at/conf.c: Likewise.
+	* i386/i386at/fd.c: Likewise.
+	* i386/i386at/idt.h: Likewise.
+	* i386/i386at/immc.c: Likewise.
+	* i386/i386at/kd.c: Likewise.
+	* i386/i386at/kd_event.c: Likewise.
+	* i386/i386at/kd_mouse.c: Likewise.
+	* i386/i386at/model_dep.c: Likewise.
+	* i386/i386at/rtc.c: Likewise.
+	* i386/include/mach/i386/asm.h: Likewise.
+	* i386/include/mach/i386/eflags.h: Likewise.
+	* i386/include/mach/i386/mach_i386.defs: Likewise.
+	* i386/include/mach/i386/multiboot.h: Likewise.
+	* i386/include/mach/i386/trap.h: Likewise.
+	* i386/include/mach/i386/vm_types.h: Likewise.
+	* i386/include/mach/sa/stdarg.h: Likewise.
+	* i386/intel/pmap.c: Likewise.
+	* i386/intel/pmap.h: Likewise.
+	* include/alloca.h: Likewise.
+	* include/device/device_types.defs: Likewise.
+	* include/device/device_types.h: Likewise.
+	* include/device/disk_status.h: Likewise.
+	* include/device/net_status.h: Likewise.
+	* include/mach/mach.defs: Likewise.
+	* include/mach/memory_object.defs: Likewise.
+	* include/mach/std_types.defs: Likewise.
+	* include/mach_debug/hash_info.h: Likewise.
+	* include/mach_debug/ipc_info.h: Likewise.
+	* include/mach_debug/mach_debug.defs: Likewise.
+	* include/mach_debug/mach_debug_types.defs: Likewise.
+	* include/mach_debug/mach_debug_types.h: Likewise.
+	* include/mach_debug/vm_info.h: Likewise.
+	* include/mach_debug/zone_info.h: Likewise.
+	* include/sys/ioctl.h: Likewise.
+	* include/sys/time.h: Likewise.
+	* ipc/ipc_entry.h: Likewise.
+	* ipc/ipc_hash.h: Likewise.
+	* ipc/ipc_init.c: Likewise.
+	* ipc/ipc_kmsg.c: Likewise.
+	* ipc/ipc_kmsg.h: Likewise.
+	* ipc/ipc_marequest.c: Likewise.
+	* ipc/ipc_marequest.h: Likewise.
+	* ipc/ipc_mqueue.c: Likewise.
+	* ipc/ipc_mqueue.h: Likewise.
+	* ipc/ipc_notify.c: Likewise.
+	* ipc/ipc_notify.h: Likewise.
+	* ipc/ipc_object.c: Likewise.
+	* ipc/ipc_object.h: Likewise.
+	* ipc/ipc_port.c: Likewise.
+	* ipc/ipc_port.h: Likewise.
+	* ipc/ipc_pset.c: Likewise.
+	* ipc/ipc_pset.h: Likewise.
+	* ipc/ipc_right.c: Likewise.
+	* ipc/ipc_right.h: Likewise.
+	* ipc/ipc_space.c: Likewise.
+	* ipc/ipc_space.h: Likewise.
+	* ipc/mach_debug.c: Likewise.
+	* ipc/mach_msg.c: Likewise.
+	* ipc/mach_msg.h: Likewise.
+	* ipc/mach_port.c: Likewise.
+	* kern/act.c: Likewise.
+	* kern/assert.h: Likewise.
+	* kern/ast.c: Likewise.
+	* kern/ast.h: Likewise.
+	* kern/bootstrap.c: Likewise.
+	* kern/counters.c: Likewise.
+	* kern/counters.h: Likewise.
+	* kern/debug.h: Likewise.
+	* kern/exception.c: Likewise.
+	* kern/host.h: Likewise.
+	* kern/ipc_host.c: Likewise.
+	* kern/ipc_host.h: Likewise.
+	* kern/ipc_kobject.c: Likewise.
+	* kern/ipc_mig.c: Likewise.
+	* kern/ipc_tt.c: Likewise.
+	* kern/ipc_tt.h: Likewise.
+	* kern/kalloc.h: Likewise.
+	* kern/lock_mon.c: Likewise.
+	* kern/mach_clock.c: Likewise.
+	* kern/mach_factor.c: Likewise.
+	* kern/mach_param.h: Likewise.
+	* kern/machine.c: Likewise.
+	* kern/processor.c: Likewise.
+	* kern/profile.c: Likewise.
+	* kern/queue.h: Likewise.
+	* kern/sched.h: Likewise.
+	* kern/startup.c: Likewise.
+	* kern/syscall_emulation.h: Likewise.
+	* kern/syscall_subr.c: Likewise.
+	* kern/syscall_subr.h: Likewise.
+	* kern/syscall_sw.c: Likewise.
+	* kern/syscall_sw.h: Likewise.
+	* kern/task.h: Likewise.
+	* kern/thread_swap.h: Likewise.
+	* kern/time_out.h: Likewise.
+	* kern/time_stamp.c: Likewise.
+	* kern/time_stamp.h: Likewise.
+	* kern/timer.c: Likewise.
+	* kern/timer.h: Likewise.
+	* kern/xpr.c: Likewise.
+	* kern/xpr.h: Likewise.
+	* kern/zalloc.c: Likewise.
+	* kern/zalloc.h: Likewise.
+	* linux/dev/drivers/block/ide.c: Likewise.
+	* linux/dev/include/linux/blk.h: Likewise.
+	* linux/src/include/linux/cdrom.h: Likewise.
+	* linux/src/include/linux/md.h: Likewise.
+	* util/cpu.h: Likewise.
+	* vm/memory_object.c: Likewise.
+	* vm/memory_object.h: Likewise.
+	* vm/pmap.h: Likewise.
+	* vm/vm_debug.c: Likewise.
+	* vm/vm_external.h: Likewise.
+	* vm/vm_fault.c: Likewise.
+	* vm/vm_fault.h: Likewise.
+	* vm/vm_kern.h: Likewise.
+	* vm/vm_map.c: Likewise.
+	* vm/vm_map.h: Likewise.
+	* vm/vm_object.h: Likewise.
+	* vm/vm_pageout.c: Likewise.
+	* vm/vm_pageout.h: Likewise.
+	* vm/vm_user.h: Likewise.
+
+2001-01-28  Roland McGrath  <roland@frob.com>
+
+	* kern/zalloc.c (zalloc): Change panics for exhausted zone to include
+	the zone name.
+
+2001-01-09  Marcus Brinkmann  <marcus@gnu.org>
+
+	* include/device/device_types.h: New get_status call
+	DEV_GET_RECORDS to get the number of records of a device (rather
+	than the number of bytes). Accordingly define
+	DEV_GET_RECORDS_DEVICE_RECORDS, DEV_GET_RECORDS_RECORD_SIZE and
+	DEV_GET_RECORDS_COUNT.
+
+	* linux/dev/glue/block.c (device_get_status): Handle
+	DEV_GET_RECORDS.
+
+2000-11-26  David Welch  <david.welch@seh.ox.ac.uk>
+
+	* i386/Makefrag (i386-installed-headers): Removed dead files
+	from the list of headers to be installed
+
+2000-11-26  Marcus Brinkmann  <marcus@gnu.org>
+
+	* linux/src/drivers/net/tulip.c: Updated to version
+	from Linux 2.2.17 (I am amazed that 2.2.x drivers work).
+	Suggested by Jason Henry Parker <jasonp@uq.net.au>.
+
+2000-10-29  Roland McGrath  <roland@frob.com>
+
+	Remove numerous dead header files.
+	Suggested by Igor Khavkine <i_khavki@alcor.concordia.ca>.
+	* i386/include/mach/i386/bios.h: Dead file removed.
+	* i386/include/mach/i386/code16.h: Dead file removed.
+	* i386/include/mach/i386/debug_reg.h: Dead file removed.
+	* i386/include/mach/i386/dpmi.h: Dead file removed.
+	* i386/include/mach/i386/far_ptr.h: Dead file removed.
+	* i386/include/mach/i386/paging.h: Dead file removed.
+	* i386/include/mach/i386/pio.h: Dead file removed.
+	* i386/include/mach/i386/pmode.h: Dead file removed.
+	* i386/include/mach/i386/proc_reg.h: Dead file removed.
+	* i386/include/mach/i386/seg.h: Dead file removed.
+	* i386/include/mach/i386/time_stamp.h: Dead file removed.
+	* i386/include/mach/i386/tss.h: Dead file removed.
+	* i386/include/mach/i386/vcpi.h: Dead file removed.
+	* i386/include/mach/proc_ops.h: Dead file removed.
+	* i386/include/mach/sa/sys/varargs.h: Dead file removed.
+	* i386/include/mach/setjmp.h: Dead file removed.
+	* include/mach/proc_ops.h: Dead file removed.
+	* Makefile.in (mach-headers): Remove proc_ops.h.
+	* i386/Makefrag (i386-installed-headers): Likewise.
+	(installed-headers): Don't touch this any more.
+	* i386/Files: Update for removed files.
+
+2000-09-29  Marcus Brinkmann  <marcus@gnu.org>
+
+	* i386/i386at/conf.c (dev_name_list): Don't use MACH_COM to check
+	if com support is enabled, but NCOM, as it used to be.
+
+2000-09-24  OKUJI Yoshinori  <okuji@gnu.org>
+
+	* linux/dev/glue/block.c: Reverted the changes at 2000-08-17.
+	Reported by Brent Fulgham <brent.fulgham@xpsystems.com>.
+
+2000-09-19  Marcus Brinkmann  <marcus@gnu.org>
+
+	* linux/dev/glue/block.c (init_partition): Move initialization
+	of MASK until it is asserted that gd is non-NULL.
+
+2000-08-17  OKUJI Yoshinori  <okuji@gnu.org>
+
+	* linux/dev/glue/block.c (rdwr_partial): Mask the minor device
+	number with MINOR_SHIFT bits, when indexing the array of
+	partitions. Reported by Marius Vollmer <mvo@zagadka.ping.de>.
+	(init_partition): Likewise.
+	(check_limit): Likewise.
+	(device_get_status): Likewise.
+
+2000-07-27  Marcus Brinkmann  <marcus@gnu.org>
+
+	* Fix omissions in last change:
+	* linux/src/arch/i386/lib/delay.S: Now really delete the file.
+	* linux/src/arch/i386/lib/delay.c: Now really add the file.
+
+2000-07-04  Marcus Brinkmann <marcus@gnu.org>
+
+	* debian/changelog: Add entry for new Debian upload.
+        * linux/dev/drivers/scsi/seagate.c (WRITE_CONTROL, WRITE_DATA):
+        Added from linux 2.2.15.
+        (__asm__ constructs): Replace with equivalent C code from linux 2.2.15
+        to support gcc-2.95.
+        * linux/src/drivers/scsi/in2000.h: Update asm code to linux 2.2.15.
+	* linux/src/drivers/scsi/ppa.c: Replace asm code with equivalent
+	C code from linux 2.2.15.
+
+2000-02-06  Stefan Weil <stefan.weil@de.heidelberg.com>
+
+	* device/subrs.c: Fixed compiler warning.
+	* ddb/db_output.c, kern/bootstrap.c, kern/debug.c, kern/printf.c:
+	Replaced varargs.h by stdarg.h. Fixed prototypes (const char *fmt).
+	* ddb/db_output.h: Use prototype for db_printf.
+	* i386/Files: removed varargs.h.
+	* i386/i386/pit.h: Fixed compiler warning.
+	* i386/i386at/model_dep.c: Tried to fix compiler warning.
+	* i386/include/mach/sa/sys/varargs.h: Removed.
+	* i386/linux/Makefile.in: Removed delay.S, added delay.c.
+	* linux/dev/include/asm-i386/segment.h: Support gcc-2.95.
+	* linux/dev/include/asm-i386/string.h,
+	linux/src/include/asm-i386/string.h: Update from linux-2.2.14.
+	* linux/dev/lib/vsprintf.c: Fixed compiler warning.
+	* linux/src/include/asm-i386/delay.h: Update from linux-2.2.14.
+	* linux/src/arch/i386/lib/delay.c: Copy from linux-2.2.14.
+	* linux/src/include/asm-i386/string.h: Update from linux-2.2.14.
+
+1999-10-08  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* linux/src/drivers/net/3c59x.c: Updated to version 0.99L of the
+	driver from ftp://cesdis.gsfc.nasa.gov/linux/drivers/3c59x.c, in
+	order to support the 3c509c card, as requested by Jeff Bailey
+	<jbailey@nisa.net>.
+
+1999-09-17  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* linux/dev/drivers/block/ide.c (do_request) [MACH]: In "bad
+	access" printf, actually print the number of sectors of the
+	partition.
+
+1999-10-05  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* i386/intel/pmap.c (pmap_bootstrap): Use _start instead of start.
+	* i386/i386/trap.c (kernel_trap): Likewise.
+
+1999-10-04  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* configure.in: Remove AC_CHECK_TOOL(MAKE,...) check.
+	* Makefile.in (MAKE): Variable removed.  We require GNU make anyway,
+	and it always sets MAKE.
+	* configure: Regenerated.
+
+	* Makefile.in (clib-routines.o, check-clib-routines, clib-routines.d):
+	Remove these rules, replace with:
+	(kernel.o): New target, relocatable object linked from kernel objects.
+	(kernel-undef, kernel-undef-bad): New targets, glean undefined symbols
+	from kernel.o.
+	(clib-routines.o): New target, use those to select symbols from libc.
+	(clib-routines): Add some symbols; move defn to kernel linking page.
+	This variable is now a list of symbols allowed to be undefined,
+	rather than a prescriptive list of symbols always grabbed from libc.
+	(kernel): Rewrite this rules to just link kernel.o and clib-routines.o
+	together to make the kernel image.
+
+1999-09-15  Mark Kettenis  <kettenis@gnu.org>
+
+	* i386/i386/user_ldt.c: Fix user LDT management.
+	(i386_set_ldt): Prevent thrashing the LDT for the current thread.
+	Correctly calculate size of new LDT.  Set base adress of the LDT
+	descriptor to the linear address of the LDT instead of the kernel
+	virtual address.  Copy descriptors from the default LDT if there
+	is no old LDT for the current thread.  Call switch_ktss if we are
+	setting a new LDT for the current thread.
+	(i386_get_ldt): Fix bug in copying out the descriptors.
+
+1999-09-09  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* linux/src/drivers/net/rtl8139.c (RX_BUF_LEN_IDX): Reduce from 3
+	to 2.  (64K exceeds the limits in linux/dev/glue/kmem.c:kmalloc.)
+	(rtl8129_open): If we fail to get the memory we need, then free
+	the IRQ before returning.
+	Reported by Daniel Kobras <daniel.kobras@student.uni-tuebingen.de>.
+
+1999-09-07  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* linux/src/drivers/net/yellowfin.c (yellowfin_probe): Return
+	correct value.  Reported by Marcus Brinkmann
+	<Marcus.Brinkmann@ruhr-uni-bochum.de>.
+
+	* linux/dev/drivers/net/Space.c: Declare tc515_probe.  Reported by
+	Marcus Brinkmann <Marcus.Brinkmann@ruhr-uni-bochum.de>.
+
+1999-09-04  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* vm/vm_resident.c (vm_page_grab): Only block unprivileged
+	allocations over vm_page_external_limit if they are actually
+	external allocations.  Reported by Mark Kettenis
+	(kettenis@wins.uva.nl>.
+
+1999-08-10  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* i386/i386at/model_dep.c (init_alloc_aligned): Revert previous
+	change except for the one to AVAIL_NEXT.  All the rest of the
+	previous code was correct.  Correction from Momchil Velikov
+	(velco@fadata.bg).
+
+1999-07-23  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* Drivers.macros (AC_DRIVER): Use `test' instead of `[ ... ]'.
+	Reported by "Momchil 'Velco' Velikov" <velco@fadata.bg>.
+
+1999-07-20  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* linux/dev/drivers/block/genhd.c (check_partition): Change message
+	to say these are only the DOS partitions.
+	* i386/linux/dev/include/linux/autoconf.h (CONFIG_BSD_DISKLABEL,
+	CONFIG_SMD_DISKLABEL): #undef these.  The dev/glue/block.c code
+	deals with BSD disklabels and expects the Linux genhd.c code to
+	handle only the DOS partitions; having genhd.c do BSD disklabels
+	too just confuses things.
+
+	Force subdirectory targets so they get recompiled properly.
+	* i386/Makefile.in (linux/linux.o): Depend on FORCE instead of linux.
+	(FORCE): New target.
+	* i386/Makefrag (i386/sysdep.o, FORCE): Likewise.
+
+1999-07-11  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* i386/i386at/model_dep.c (init_alloc_aligned): Make the checks
+	correctly for addresses falling into skip regions.  Reported by
+	Momchil Velikov (velco@fadata.bg).
+
+1999-07-01  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* i386/linux/Makefile.in: For each .o file in $(linux-objs)
+	include a corresponding .d file, unless `no_deps' is `t'.
+	(make-deps): New function.
+	(%.d): New pattern rules for building %.d from %.c and %.S.
+
+1999-06-29  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* vm/vm_resident.c (vm_page_grab): Don't bounce requests when
+	vm_page_external_count == vm_page_external_limit, so that before
+	initialization is complete we can still allocate memory without
+	relying on current_thread.
+	(vm_page_wait): Also block if we are over the external page
+	limit.
+	* vm/vm_pageout.c (vm_pageout_scan): Rewrite the
+	scan-for-pages-to-pageout loop to not crash when we hit the end of
+	the inactive queue; instead jump back to the
+	pause-for-a-little-while code.
+
+1999-06-27  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* vm/vm_resident.c (vm_page_external_count): Define variable.
+	(vm_page_grab): New argument `external'.  All callers changed.
+	Keep track of number of externally managed pages.  Don't let
+	non-privileged threads exceed the externally-managed page limit.
+	(vm_page_grab_contiguous_pages): New argument `external'.  All
+	callers changed.  Keep track of number of externally managed
+	pages.  Don't let non-privileged threads exceed the
+	externally-managed page limit.
+	(vm_page_convert): New argument `external', handed off to
+	vm_page_grab.  All callers changed.
+	(vm_page_release): New argument `external'.  All callers
+	changed. Keep track of number of externally managed pages.
+	(vm_page_bootstrap): Initialize M->external.
+	(vm_page_external_limit): Define new variable.
+	(vm_page_grab_phys_addr, vm_page_alloc): Add new arg for
+	vm_page_grab.
+	(vm_page_free): Provide new arg to vm_page_release.
+	* vm/vm_page.h (vm_page_external_limit, vm_page_external_count):
+	New variables.
+	(struct vm_page): New members `external' and `extcounted'.
+	(vm_page_grab, vm_page_release, vm_page_convert): Specify new
+	argument.
+	* vm/vm_pageout.c (vm_pageout): Initialize vm_page_external_limit
+	and vm_page_external_target.
+	(VM_PAGE_EXTERNAL_LIMIT, VM_PAGE_EXTERNAL_TARGET): New macro.
+	(vm_page_external_target): New variable.
+	(vm_pageout_scan): Regard "too many externally managed pages" as a
+	reason to keep doing work, but if that's the only reason we're
+	doing work, then the only thing we do is schedule cleaning of
+	pages.  Help keep track of the number of externally managed pages
+	that we care about.
+	* i386/intel/pmap.c (pmap_page_table_page_alloc): Add new arg for
+	vm_page_grab.
+	* linux/dev/glue/block.c (alloc_buffer, device_read): Likewise.
+	* vm/vm_map.c (vm_map_copy_steal_pages): Likewise.
+	* vm/vm_fault.c (vm_fault_page): Add new args for vm_page_grab and
+	vm_page_convert.
+
+	* vm/vm_pageout.c (VM_PAGEOUT_BURST_WAIT): Reduce to 10ms/page.
+	(VM_PAGEOUT_EMPTY_WAIT): Reduce to 75 ms.
+	(VM_PAGE_FREE_RESERVED): Increase to 50 pages.
+	(VM_PAGEOUT_RESERVED_INTERNAL): Adjust to `(reserve) - 25'.
+	(VM_PAGEOUT_RESERVED_REALLY): Adjust to `(reserve) - 40'.
+
+1999-06-21  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* i386/Files: Don't mention i386/pc/Makerules,
+	i386/include/Makerules, or i386/util/Makerules.
+
+	* Makefile.in (all-real-archs): Delete variable.
+	(dist): No longer make `machine' symlink.
+
+	* Makefile.in (dist): Sanify file permissions before building tar
+	file.
+
+	* i386/Subdirs: Remove i386/i386at/boot.
+
+Sun Jun 20 18:33:59 1999  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* version.c (version): Updated to version 1.2.
+
+	* i386/Files: Regenerated.
+	* i386/Subdirs: Regenerated.
+
+	* linux/Files: New file.
+	* linux/Subdirs: New file.
+	* Makefile.in (all-archs): Add `linux'.
+	(all-real-archs): New variable.
+	(dist): Create `machine' symlink only on
+	$(all-real-archs).
+
+	* Makefile.in (dist): Use `cp' instead of `ln'.
+
+	* config.guess: Updated from autoconf 2.13.
+	* config.sub: Likewise.
+
+1999-06-16  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* linux/dev/drivers/net/Space.c (ethif_probe): Probe tc59x_probe
+	(CONFIG_VORTEX) after el3_probe (CONFIG_EL3), because the latter
+	card matches the former probe, but the driver doesn't work with
+	it.  Reported by Marcus Brinkmann <brinkmd@debian.org>.
+
+	* Drivers.macros (AC_DRIVER): Only turn on driver if $enableval is
+	not `no'.  Reported by Kalle Olavi Niemitalo <tosi@ees2.oulu.fi>.
+
+1999-06-15  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* ipc/ipc_init.c (ipc_bootstrap): Don't make the IOT_PORT zone
+	exhaustible, because allocation of ports for internal objects
+	panics if zalloc fails.
+
+1999-06-07  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* linux/dev/drivers/block/genhd.c [MACH] (mach_minor): New variable.
+	(add_bsd_partition): New function.
+	(bsd_disklabel_partition) [MACH]: Call add_bsd_partition.
+	(msdos_partition) [MACH]: Set mach_minor to MINOR before
+	calling bsd_disklabel_partition.
+	* linux/dev/drivers/block/ide.c (do_request) [MACH]: Fix "bad access"
+	message.
+
+1999-06-02  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* kern/bootstrap.c (build_args_and_stack): If kernel_cmdline is
+	nonempty, give the bootstrap task an environment variable of
+	"MULTIBOOT_CMDLINE=kernel command line" on its stack.
+
+1999-05-29  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* kern/startup.c (start_kernel_threads): Call record_time_stamp to
+	reset the kernel task's creation_time field, so it's not zero.
+
+1999-05-24  Mark Kettenis  <kettenis@gnu.org>
+
+	* i386/i386/fpu.c (fp_free): Clear task switch flag before calling
+	fwait.
+	(fpu_get_state): Only save FPU state info if the live FPU state
+	belongs to our target, i.e. if THREAD is the current thread.
+	(fp_load): Print warning if we try to load an invalid FPU state,
+	and reset the FPU to some sane state instead.
+
+1999-05-23  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* kern/task.c (task_info): Allow count for TASK_BASIC_INFO to be less
+	two words, not just one.  The new member creation_time is two words.
+
+1999-05-22  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* linux/configure: Regenerated.
+
+1999-05-21  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* linux/configure.in: Fix names dummy -> dummy.in in AC_OUTPUT call.
+
+1999-05-14  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* i386/linux/Drivers.in (linux_DRIVER): New macro, does AC_DRIVER and
+	defines alias for Linux module name.  Use that for all single-module
+	Linux drivers, so we don't forget to define any of the aliases for the
+	Linux module names.
+	* i386/linux/configure: Regenerated.
+
+1999-04-28  OKUJI Yoshinori  <okuji@localhost>
+
+	* linux/dev/drivers/block/genhd.c (bsd_disklabel_partition) [MACH]:
+	Print BSD slices, using Mach device syntax instead of Linux extented
+	partition syntax.
+
+1999-05-01  Mark Kettenis  <kettenis@gnu.org>
+
+	* linux/dev/glue/block.c (device_get_status): Always set
+	status_count to DEV_GET_STATUS_COUNT if flavor is DEV_GET_SIZE.
+
+1999-04-30  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* i386/linux/Drivers.in: Don't create asm-${systype} symlinks here.
+	* linux/configure.in: New file.  Create them here instead.
+	* linux/dummy.in: New file, used by configure.
+	* linux/configure: New file (generated by autoconf).
+	* configure.in: Configure in linux subdir.
+	* configure: Regenerated.
+
+	* i386/configure.in: Require only autoconf 2.12, not 2.13.
+	* i386/configure: Regenerated.
+
+	* aclocal.m4 (hurd_SYSTYPE): New macro.
+	* i386/linux/Drivers.in: Use it.
+	* i386/linux/configure: Regenerated.
+
+Wed Apr 28 02:17:51 1999  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* linux/src/drivers/net/3c59x.c: Upgrade to Linux 2.2.1 version.
+	(vortex_start_xmit): Don't frob VP->stat.tx_bytes.
+	(boomerang_start_xmit): Likewise.
+	(vortex_rx): Don't frob VP->stats.rx_bytes.
+	(boomerang_rx): Likewise.
+	Requested by Jeff Bailey (jbailey@nisa.net).
+
+Mon Apr 26 02:13:02 1999  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* Makefile.in (objfiles): Don't add $(systype)/sysdep.o here.
+	($(systype)/sysdep.o): Delete rule.
+	(clean, distclean, mostlyclean, maintainerclean, install-headers,
+	install-kernel): Don't do recursive make here.
+	* i386/Makefrag (objfiles): Add i386/sysdep.o to the list.
+	(i386/sysdep.o): New rule.
+	(clean): Depend on i386-clean.
+	(distclean): Depend on i386-distclean.
+	(mostlyclean): Depend on i386-mostlyclean.
+	(maintainerclean): Depend on i386-maintainerclean.
+	(install-headers): Depend on i386-install-headers.
+	(install-kernel): Depend on i386-install-kernel.
+	(i386-clean, i386-distclean, i386-mostlyclean,
+	i386-maintainerclean, i386-install-kernel, i386-install-headers):
+	New rules.
+
+1999-04-14  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* version.c (version): Update to 1.1.92.
+
+Sun Mar 14 18:53:01 1999  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* device/ds_routines.c (ds_read_done): When touching memory to
+	mark it dirty, make sure we say "volatile" so the compiler doesn't
+	optimize it out.
+
+1999-04-12  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* i386/linux/Drivers.in: Fix the source paths for `asm'	symbolic
+	links. Reported by KONISHI Toru <sting@mb.infoweb.ne.jp>.
+
+	* linux/dev/drivers/block/ide.c (init_hwif_data) [MACH]: Print Mach
+	device name instead of Linux one.
+	* linux/dev/drivers/block/genhd.c (disk_name): Likewise.
+	* linux/dev/drivers/scsi/sd.c (sd_init_onedisk): Likewise.
+	(sd_detect): Likewise.
+	* linux/dev/drivers/sr.c (sr_detect): Likewise.
+	(get_sectorsize): Likewise.
+
+1999-03-01  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	Version 1.1.91.
+
+	* version.c (version): Update to 1.1.91.
+
+1999-03-01  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* i386/linux/Drivers.in: Fix linking paths.
+	* i386/linux/Makefile.in: Corrent include paths and fix
+	Drivers.macros location.
+
+1999-02-28  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* Makefile.in (clean): Don't move device-drivers.h, because it is
+	not in the top directory any longer.
+	(distclean): Remove config.cache and config.log.
+	* i386/Makefile.in (distclean): Remove config.status, config.log
+	and Makefile.
+	* i386/linux/Makefile.in (distclean): Remove config.status,
+	config.log, Makefile and device-drivers.h.
+
+1999-02-27  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* i386/linux/Drivers.in: Don't link dev/include/asm-i386 to
+	dev/include/asm. Check if directories already exist before
+	mkdir_p's. Link directories manually, because AC_LINK_FILES
+	is weak in linking files from non-current directories.
+
+	* i386/i386at/i386at_ds_routines.c: Include
+	<i386/linux/device-drivers.h> instead of <linux/device-drivers.h>.
+	* device/ds_routines.c [LINUX_DEV]: Likewise.
+	* i386/linux/Makefile.in (linux-gen-flags): Fix an extra slash.
+	(distclean): Remove asm links.
+	* linux/src/COPYING: Copied from linux-2.0.36.
+
+1999-02-27  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* Makefile.in: Omit to detect if com or lpr is used, and don't use
+	linux.o.
+	(objfiles): Add $(systype)/sysdep.o.
+	(clean): Chain the target to $(systype).
+	(distclean): Likewise.
+	(mostlyclean): Likewise.
+	(maintainer-clean): Likewise.
+	(install-headers): Likewise.
+	(install-kernel): Likewise.
+	* configure.in: AC_CONFIG_SUBDIRS ${systype} instead of linux.
+	(--disable-linuxdev): Deleted.
+	(--disable-com): Likewise.
+	(--enable-lpr): Likewise.
+	* i386/Makefile.in: New file.
+	* i386/configure.in: Likewise.
+	* i386/Makefrag (DEFINES): Add -DLINUX_DEV.
+	(objfiles): Always add com.o. If MACH_LPR is defined, then add lpr.o.
+	* linux/Drivers.in: Moved to ...
+	* i386/linux/Drivers.in: ... here. Include ../../aclocal.m4.
+	(mkdir_p): New function to create the linux include dirs.
+	* linux/Makefile.in: Moved to ...
+	* i386/linux/Makefile.in: ... here, and modify so that paths
+	are valid.
+	(clean): New target.
+	(distclean): Likewise.
+	(mostlyclean): Likewise.
+	(maintainer-clean): Likewise.
+	* linux/src/include/linux/autoconf.h: Removed.
+	* linux/dev/include/linux/autoconf.h: Moved to ...
+	* i386/linux/dev/include/linux/autoconf.h: ... here.
+	* linux/dev/arch/i386/linux_emul.h: Moved to ...
+	* i386/linux/dev/include/linux_emul.h: ... here.
+	* linux/device-drivers.h.in: Moved to ...
+	* i386/linux/device-drivers.h.in: ... here.
+	* linux/aclocal.m4: Removed.
+	* linux/configure: Likewise.
+
+1999-02-14  Gordon Matzigkeit  <gord@trick.fig.org>
+
+	* Makefile.in (install-kernel): Be sure that $(bootdir) is
+	created before installing the kernel.
+
+1999-02-06  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* configure.in: Enable com by default, because current kbd and
+	mouse can't be linked without com. Reported by M. Meiarashi
+	<mes@st.rim.or.jp>.
+
+1999-02-05  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	Version 1.1.90.
+
+	* version.c (version): Update to 1.1.90.
+
+1999-02-04  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* device/kmsg.c (kmsginit): Add a missing semicolon.
+	(kmsggetstat): Fix typos,
+	DEV_GET_DEVICE_SIZE -> DEV_GET_SIZE_DEVICE_SIZE and
+	DEV_GET_RECORD_SIZE -> DEV_GET_SIZE_RECORD_SIZE.
+	(kmsg_putchar): Fix a typo kmsg_done_init -> kmsg_init_done.
+	* linux/dev/glue/block.c (device_get_status): Allocate a hd_geometry
+	on the stack.
+	* linux/dev/drivers/block/ide.c: New file.
+	* linux/dev/drivers/scsi/sd_ioctl.c: New file.
+
+1999-02-02  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* i386/i386at/kd_event.c (kbdgetstat): Fix a typo
+	DEV_GET_SIZES -> DEV_GET_SIZE.
+	* i386/i386at/kd_mouse.c (mousegetstat): Likewise.
+	* device/kmsg.c (kmsggetstat): Likewise.
+
+1999-02-01  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* linux/dev/glue/block.c (dev_getstat): Fix a missing `struct'.
+	* device/cons.c (cninit): Don't call kmsginit.
+	* kmsg.c (kmsg_buffer): Defined as static.
+	(kmsg_write_offset): Likewise.
+	(kmsg_read_offset): Likewise.
+	(kmsg_read_queue): Likewise.
+	(kmsg_in_use): Likewise.
+	(kmsg_lock): Likewise.
+	(kmsginit): Likewise, and call queue_init instead of setting
+	PREV and NEXT manually.
+	(kmsg_done_init): New variable.
+	(kmsg_putchar): Call kmsginit if not initialized yet.
+	(kmsggetstat): New function.
+	* kmsg.h (kmsggetstat): Add the prototype.
+	* i386/i386at/kd_event.c (kbdgetstat): Handle DEV_GET_SIZE.
+	(kbdread): Check if the amount a user specify is a multiple
+	of sizeof(kd_event).
+	* i386/i386at/kd_mouse.c (mousegetstat): New function.
+	(mouseread): Check if the amount a user specify is a multiple
+	of sizeof(kd_event).
+	* i386/i386at/conf.c (dev_name_list): Set the mouse getstat entry
+	to mousegetstat and the kmsg getstat entry to kmsggetstat.
+	Use MACH_COM instead of NCOM to determine if com is used.
+	Use MACH_LPR instead of NLPR to determine if lpr is used.
+	* configure.in (--enable-com): New option.
+	(--enable-lpr): Likewise.
+	* Makefile.in (enable_com): New variable.
+	(enable_lpr): Likewise.
+	* i386/Makefrag (i386at-files): Remove com.c.
+	(objfiles): Add com.o if enable_com is yes, and lpr.o if enable_lpr
+	is yes.
+
+Tue Jan 26 21:36:10 1999  Thomas Bushnell, BSG  <tb@mit.edu>
+
+	* kern/exception.c (exception_no_server): Correctly comment out
+	the suspend code.  (This should have happened on 17 April 1997,
+	but apparently I did it backwards.)
+
+1999-01-26  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* device/kmsg.c (kmsgopen): Added simple_lock and simple_unlock.
+	(ksmgclose): Likewise.
+
+1999-01-25  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* Makefile.in (install-headers): New target for installing only
+	the headers.
+	(install-kernel): New target for installing only the kernel.
+	(mkheaderdirs): New target for making the headers
+	installation directories.
+	(mkkerneldirs): New target for making the kernel
+	installation directory.
+	(install): Do nothing by itself, but depend on install-kernel
+	and install-headers.
+
+1999-01-24  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* device/kmsg.h (KMSGBUFSIZE): Deleted.
+	* device/kmsg.c: Rewritten completely to provide stream interface.
+	* linux/dev/glue/block.c (device_getstat): Added V_GETPARMS support.
+	* config.guess: New version from automake-1.4.
+	* config.sub: Likewise.
+	* install-sh: Likewise.
+
+	Some changes were merged from gnumach-m68k by
+	Aymeric Vincent <vincent@emi.u-bordeaux.fr>.
+
+	* Makefile.in (clean): Don't hang if device-drivers.h doesn't exist.
+	* linux/Makefile.in (CPPFLAGS): Fix a typo.
+
+1999-01-16  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* device/kmsg.c: Fixed the copyright notice.
+	(MACH_KMSG): Removed.
+	* Makefile.in (enable_kmsg): New variable.
+	(objfiles): Add kmsg.o, if and only if enable_kmsg is yes.
+
+1999-01-10  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* i386/i386at/kd.c: Applied a keymap patch. Reported by
+	Marcus Brinkmann <Marcus.Brikmann@ruhr-uni-bochum.de>.
+	* i386/i386at/kd.h: Likewise.
+
+1998-12-30  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* linux/dev/glue/net.c (dev_alloc_skb): Change the skb arragement.
+	(dev_kfree_skb): Free only skb.
+	(device_write): Keep skb elements up-to-date.
+
+1998-12-18  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* Makefile.in (objfiles): Add kmsg.o.
+	* device/cons.c: Include <device/io_req.h>.
+	* device/kmsg.c: Rewritten almost entirely.
+
+1998-12-06  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	Add kmsg device.
+
+	* Makefile.in (device-files): Add kmsg.c and kmsg.h.
+	* configure.in (--enable-kmsg): New option.
+	* device/cons.c: Include kmsg.h.
+	(cninit): Call kmsginit if MACH_KMSG is defined.
+	(cnputc): Call kmsg_putchar if MACH_KMSG is defined.
+	* device/kmsg.c: New file.
+	* device/kmsg.h: Likewise.
+	* i386/i386at/conf.c (dev_name_list): Add kmsg entry.
+
+1998-12-02  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* configure.in: Fix linuxdev option handling.
+	* linux/Drivers.in: Remove linuxdev option and fix linking files.
+	* linux/Makefile.in: Replace @DEFS@ with -DLINUX_DEV.
+	* linux/dev/arch/i386/kernel/irq.c: Include missing header files.
+	* linux/dev/arch/i386/kernel/setup.c: Include <device-drivers.h>.
+	* linux/dev/glue/kmem.c: Add printf declaration.
+	* linux/dev/glue/misc.c: Include <linux/types.h>.
+	* linux/dev/init/main.c: Call linux_sched_init instead of sched_init.
+	* linux/dev/kernel/sched.c: Add timer_bh declaration.
+	(tqueue_bh): Fix the argument.
+	(linux_sched_init): Renamed from sched_init.
+
+1998-12-01  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* i386/i386at/i386at_ds_routines.c: Include <linux/device-drivers.h>
+	only if LINUX_DEV is defined. Reported by UCHIYAMA Yasushi
+	<uch@nop.or.jp>.
+	* device/ds_routines.c: Likewise.
+	* configure.in: AC_CONFIG_SUBDIRS(linux) instead of linuxdev.
+	(--disable-linuxdev): New option.
+	* linux/Makefile.in (CPPFLAGS): Remove -DLINUX_DEV, and add @DEFS@.
+	(objfiles): Add linux.o only if LINUX_DEV is defined.
+	* linux/Drivers.in (--disable-linuxdev): New option.
+	* i386/Makefrag (DEFINES): Remove -DLINUX_DEV.
+
+1998-11-30  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	Clean up linux emulation code to make it architecture-independent
+	as much as possible.
+
+	* linux: Renamed from linuxdev.
+	* Makefile.in (objfiles): Add linux.o instead of linuxdev.o.
+	(MAKE): New variable. Used for the linux.o target.
+	* configure.in: Add AC_CHECK_TOOL(MAKE, make).
+	* i386/i386/spl.h: Include <i386/ipl.h>, for compatibility with
+	OSF Mach 3.0. Suggested by Elgin Lee <ehl@funghi.com>.
+	* linux/src: Renamed from linux/linux.
+	* linux/dev: Renamed from linux/mach.
+	* linux/Drivers.in (AC_INIT): Use dev/include/linux/autoconf.h,
+	instead of mach/include/linux/autoconf.h.
+	* Makefile.in (all): Target ../linux.o instead of ../linuxdev.o.
+	* linux/dev/drivers/block/genhd.c: Include <machine/spl.h> instead
+	of <i386/ipl.h>.
+	* linux/dev/drivers/net/auto_irq.c: Remove unneeded header files,
+	<i386/ipl.h> and <i386/pic.h>.
+	* linux/dev/init/main.c: Many i386-dependent codes moved to ...
+	* linux/dev/arch/i386/irq.c: ... here.
+	* linux/dev/arch/i386/setup.c: New file.
+	* linux/dev/arch/i386/linux_emul.h: Likewise.
+	* linux/dev/arch/i386/glue/timer.c: Merged into sched.c.
+	* linux/dev/arch/i386/glue/sched.c: Include <machine/spl.h> instead
+	of <i386/ipl.h>, and moved to ...
+	* linux/dev/kernel/sched.c: ... here.
+	* linux/dev/arch/i386/glue/block.c: Include <machine/spl.h> and
+	<linux_emul.h>, instead of i386-dependent header files, and
+	moved to ...
+	* linux/dev/glue/blocl.c: ... here.
+	* linux/dev/arch/i386/glue/net.c: Include <machine/spl.h> and
+	<linux_emul.h>, instead of i386-dependent header files, and
+	moved to ...
+	* linux/dev/glue/net.c: ... here.
+	* linux/dev/arch/i386/glue/misc.c: Remove `x86' and moved to ...
+	* linux/dev/glue/misc.c: ... here.
+	* linux/dev/arch/i386/glue/kmem.c: Moved to ...
+	* linux/dev/glue/kmem.c: ... here.
+
+1998-11-25  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* linuxdev/mach/init/main.c (linux_init): Call reserve_mach_irqs.
+	* linuxdev/mach/arch/i386/kernel/irq.c (probe_irq_on): Fix ivect
+	mishandling.
+	(probe_irq_off): Disable unnecessary IRQs. Reported by
+	UCHIYAMA Yasushi <uch@nop.or.jp>.
+	(reserve_mach_irqs): New function.
+
+1998-11-24  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* linuxdev/arch/i386/linux_init.c (linux_init): Check ivect
+	before set linux_bad_intr.
+	* linuxdev/arch/i386/linux_irq.c (probe_irq_on): Allocate only
+	if ivect is null, and set linux_intr_pri to intpri.
+
+	* linuxdev: Heavily changed. It becomes more Linux-like file
+	hierarchy as suggested by Roland McGrath <roland@frob.com>.
+	* linuxdev/linux: Contain original Linux source files.
+	* linuxdev/mach: Contain modified source files for Mach.
+	* linuxdev/mach/arch/i386/glue: XXX Contain files that are
+	not easy to segregate.
+	* Makefile.in: Call `make -C linuxdev all', instead of include
+	linuxdev/Makefrag.
+
+1998-11-23  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* linuxdev/arch/i386/linux_irq.c (linux_bad_intr): New function.
+	(free_irq): Set linux_bad_intr into ivect[irq].
+	* linuxdev/arch/i386/linux_init.c (linux_init):
+	Set linux_bad_intr as the default interrupt handler.
+
+	* linuxdev/include/asm-i386/string.h (strstr): Fix the
+	egcs/gcc 2.8.x bug and a linkage problem. Reported by
+	Roland McGrath <roland@frob.com>.
+
+1998-11-18  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* linuxdev/Drivers.in: Fix a typo.
+	* linuxdev/Makefrag: Likewise.
+	* linuxdev/arch/i386/linux_block.c (set_blocksize): Likewise.
+
+	* linuxdev/arch/i386/linux_kmem.c (vfree): Cast void * to
+	vm_offset_t.
+	* linuxdev/drivers/net/wavelan.p.h: Include
+	<linuxdev/drivers/net/i82586.h>, instead of <drivers/net/i82586.h>.
+	* linuxdev/drivers/scsi/aha152x.c: Define AUTOCONF.
+	* linuxdev/configure: Regenerate.
+
+1998-11-17  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* linuxdev/arch/i386/linux_misc.c (strstr): New function.
+	Because	inline version strstr is not used when use
+	egcs/gcc 2.8.x.	Reported by UCHIYAMA Yasushi <uch@nop.or.jp>.
+
+	* linuxdev/arch/i386/linux_irq.c (unmask_irq): Fix a typo.
+
+1998-11-17  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* i386/README-Drivers: Update to Linux 2.0.36 device drivers.
+	* linuxdev/Drivers.in: Likewise.
+	* linuxdev/Makefrag: Likewise.
+	* linuxdev/arch/i386/linux_lib.S: Likewise.
+	* linuxdev/device-drivers.h.in: Likewise.
+	* linuxdev/drivers/block/floppy.c: Likewise.
+	* linuxdev/drivers/block/ide.c: Likewise.
+	* linuxdev/drivers/block/ide.h: Likewise.
+	* linuxdev/drivers/net/3c505.h: Likewise.
+	* linuxdev/drivers/net/3c509.c: Likewise.
+	* linuxdev/drivers/net/3c515.c: Likewise.
+	* linuxdev/drivers/net/3c59x.c: Likewise.
+	* linuxdev/drivers/net/Space.c: Likewise.
+	* linuxdev/drivers/net/apricot.c: Likewise.
+	* linuxdev/drivers/net/de4x5.c: Likewise.
+	* linuxdev/drivers/net/eepro.c: Likewise.
+	* linuxdev/drivers/net/eepro100.c: Likewise.
+	* linuxdev/drivers/net/eexpress.c: Likewise.
+	* linuxdev/drivers/net/epic100.c: Likewise.
+	* linuxdev/drivers/net/eth16i.c: Likewise.
+	* linuxdev/drivers/net/hp100.c: Likewise.
+	* linuxdev/drivers/net/lance.c: Likewise.
+	* linuxdev/drivers/net/ne2k-pci.c: Likewise.
+	* linuxdev/drivers/net/pcnet32.c: Likewise.
+	* linuxdev/drivers/net/rtl8139.c: Likewise.
+	* linuxdev/drivers/net/tlan.c: Likewise.
+	* linuxdev/drivers/net/tulip.c: Likewise.
+	* linuxdev/drivers/net/wavelan.c: Likewise.
+	* linuxdev/drivers/pci/pci.c: Likewise.
+	* linuxdev/drivers/scsi/BusLogic.c: Likewise.
+	* linuxdev/drivers/scsi/FlashPoint.c: Likewise.
+	* linuxdev/drivers/scsi/aha152x.c: Likewise.
+	* linuxdev/drivers/scsi/aha1542.c: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx/sequencer.h: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx.c: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx_proc.c: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx_reg.h: Likewise.
+	* linuxdev/drivers/scsi/dtc.c: Likewise.
+	* linuxdev/drivers/scsi/eata.c: Likewise.
+	* linuxdev/drivers/scsi/eata.h: Likewise.
+	* linuxdev/drivers/scsi/eata_dma.c: Likewise.
+	* linuxdev/drivers/scsi/gdth.c: Likewise.
+	* linuxdev/drivers/scsi/gdth.h: Likewise.
+	* linuxdev/drivers/scsi/gdth_proc.c: Likewise.
+	* linuxdev/drivers/scsi/gdth_proc.h: Likewise.
+	* linuxdev/drivers/scsi/hosts.c: Likewise.
+	* linuxdev/drivers/scsi/in2000.c: Likewise.
+	* linuxdev/drivers/scsi/in2000.h: Likewise.
+	* linuxdev/drivers/scsi/ncr53c8xx.c: Likewise.
+	* linuxdev/drivers/scsi/ppa.h: Likewise.
+	* linuxdev/drivers/scsi/scsi.c: Likewise.
+	* linuxdev/drivers/scsi/scsicam.c: Likewise.
+	* linuxdev/drivers/scsi/sd.c: Likewise.
+	* linuxdev/drivers/scsi/seagate.c: Likewise.
+	* linuxdev/drivers/scsi/u14-34f.c: Likewise.
+	* linuxdev/drivers/scsi/u14-34f.h: Likewise.
+	* linuxdev/drivers/scsi/wd7000.c: Likewise.
+	* linuxdev/drivers/scsi/wd7000.h: Likewise.
+	* linuxdev/include/asm-i386/irq.h: Likewise.
+	* linuxdev/include/asm-i386/processor.h: Likewise.
+	* linuxdev/include/asm-i386/ptrace.h: Likewise.
+	* linuxdev/include/asm-i386/system.h: Likewise.
+	* linuxdev/include/asm-i386/unistd.h: Likewise.
+	* linuxdev/include/linux/fs.h: Likewise.
+	* linuxdev/include/linux/genhd.h: Likewise.
+	* linuxdev/include/linux/interrupt.h: Likewise.
+	* linuxdev/include/linux/ip.h: Likewise.
+	* linuxdev/include/linux/pci.h: Likewise.
+	* linuxdev/include/linux/version.h: Likewise.
+	* linuxdev/include/linux/wireless.h: Likewise.
+
+	* linuxdev/drivers/net/via-rhine.c: New file.
+	* linuxdev/drivers/scsi/aic7xxx_seq.c: Likewise.
+	* linuxdev/include/linux/rose.h: Likewise.
+
+	* linuxdev/drivers/scsi/aic7xxx_seq.h: Removed.
+	* linuxdev/configure: Regenerate.
+	* linuxdev/include/asm-i386/string.h: Fix the egcs/gcc 2.8.x problem,
+	according to http://www.suse.de/~florian/kernel+egcs.html.
+
+1998-11-14  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* Makefile.in (clib-routines.o): Add -L option to search libc.a.
+	Reported by TAKEUCHI Yoji <ytakeuch@po.iijnet.or.jp>.
+
+	* linuxdev/drivers/pci/bios32.c: Moved to ...
+	* linuxdev/arch/i386/linux_bios32.c: ... here. Because it is
+	i386-specific code.
+	* linuxdev/include/asm: Moved to ...
+	* linuxdev/include/asm-i386: ... here.
+
+	* i386/README-Drivers: Update to Linux 2.0.35 device drivers.
+	* linuxdev/Drivers.in: Likewise.
+	* linuxdev/configure: Likewise.
+	* linuxdev/device-drivers.h.in: Likewise.
+	* linuxdev/Makefrag: Likewise.
+	* linuxdev/arch/i386/linux_autoirq.c: Likewise.
+	* linuxdev/arch/i386/linux_block.c: Likewise.
+	* linuxdev/arch/i386/linux_dma.c: Likewise.
+	* linuxdev/arch/i386/linux_init.c: Likewise.
+	* linuxdev/arch/i386/linux_irq.c: Likewise.
+	* linuxdev/arch/i386/linux_kmem.c: Likewise.
+	* linuxdev/arch/i386/linux_misc.c: Likewise.
+	* linuxdev/arch/i386/linux_net.c: Likewise.
+	* linuxdev/arch/i386/linux_port.c: Likewise.
+	* linuxdev/arch/i386/linux_printk.c: Likewise.
+	* linuxdev/arch/i386/linux_sched.c: Likewise.
+	* linuxdev/arch/i386/linux_timer.c: Likewise.
+	* linuxdev/arch/i386/linux_version.c: Likewise.
+	* linuxdev/arch/i386/linux_vsprintf.c: Likewise.
+	* linuxdev/drivers/block/cmd640.c: Likewise.
+	* linuxdev/drivers/block/floppy.c: Likewise.
+	* linuxdev/drivers/block/genhd.c: Likewise.
+	* linuxdev/drivers/block/ide-cd.c: Likewise.
+	* linuxdev/drivers/block/ide.c: Likewise.
+	* linuxdev/drivers/block/ide.h: Likewise.
+	* linuxdev/drivers/block/ide_modes.h: Likewise.
+	* linuxdev/drivers/block/rz1000.c: Likewise.
+	* linuxdev/drivers/block/triton.c: Likewise.
+	* linuxdev/drivers/net/3c501.c: Likewise.
+	* linuxdev/drivers/net/3c503.c: Likewise.
+	* linuxdev/drivers/net/3c505.c: Likewise.
+	* linuxdev/drivers/net/3c507.c: Likewise.
+	* linuxdev/drivers/net/3c509.c: Likewise.
+	* linuxdev/drivers/net/3c59x.c: Likewise.
+	* linuxdev/drivers/net/8390.c: Likewise.
+	* linuxdev/drivers/net/8390.h: Likewise.
+	* linuxdev/drivers/net/Space.c: Likewise.
+	* linuxdev/drivers/net/ac3200.c: Likewise.
+	* linuxdev/drivers/net/apricot.c: Likewise.
+	* linuxdev/drivers/net/at1700.c: Likewise.
+	* linuxdev/drivers/net/atp.c: Likewise.
+	* linuxdev/drivers/net/atp.h: Likewise.
+	* linuxdev/drivers/net/de4x5.c: Likewise.
+	* linuxdev/drivers/net/de4x5.h: Likewise.
+	* linuxdev/drivers/net/de600.c: Likewise.
+	* linuxdev/drivers/net/de620.c: Likewise.
+	* linuxdev/drivers/net/depca.c: Likewise.
+	* linuxdev/drivers/net/dev.c: Likewise.
+	* linuxdev/drivers/net/e2100.c: Likewise.
+	* linuxdev/drivers/net/eepro.c: Likewise.
+	* linuxdev/drivers/net/eepro100.c: Likewise.
+	* linuxdev/drivers/net/eexpress.c: Likewise.
+	* linuxdev/drivers/net/eth16i.c: Likewise.
+	* linuxdev/drivers/net/ewrk3.c: Likewise.
+	* linuxdev/drivers/net/ewrk3.h: Likewise.
+	* linuxdev/drivers/net/hp-plus.c: Likewise.
+	* linuxdev/drivers/net/hp.c: Likewise.
+	* linuxdev/drivers/net/hp100.c: Likewise.
+	* linuxdev/drivers/net/hp100.h: Likewise.
+	* linuxdev/drivers/net/i82586.h: Likewise.
+	* linuxdev/drivers/net/lance.c: Likewise.
+	* linuxdev/drivers/net/ne.c: Likewise.
+	* linuxdev/drivers/net/net_init.c: Likewise.
+	* linuxdev/drivers/net/ni52.c: Likewise.
+	* linuxdev/drivers/net/ni52.h: Likewise.
+	* linuxdev/drivers/net/ni65.c: Likewise.
+	* linuxdev/drivers/net/ni65.h: Likewise.
+	* linuxdev/drivers/net/seeq8005.c: Likewise.
+	* linuxdev/drivers/net/seeq8005.h: Likewise.
+	* linuxdev/drivers/net/sk_g16.c: Likewise.
+	* linuxdev/drivers/net/sk_g16.h: Likewise.
+	* linuxdev/drivers/net/smc-ultra.c: Likewise.
+	* linuxdev/drivers/net/tulip.c: Likewise.
+	* linuxdev/drivers/net/wavelan.c: Likewise.
+	* linuxdev/drivers/net/wavelan.h: Likewise.
+	* linuxdev/drivers/net/wd.c: Likewise.
+	* linuxdev/drivers/net/znet.c: Likewise.
+	* linuxdev/drivers/pci/pci.c: Likewise.
+	* linuxdev/drivers/scsi/53c7,8xx.h: Likewise.
+	* linuxdev/drivers/scsi/53c78xx.c: Likewise.
+	* linuxdev/drivers/scsi/53c8xx_d.h: Likewise.
+	* linuxdev/drivers/scsi/AM53C974.c: Likewise.
+	* linuxdev/drivers/scsi/AM53C974.h: Likewise.
+	* linuxdev/drivers/scsi/BusLogic.c: Likewise.
+	* linuxdev/drivers/scsi/BusLogic.h: Likewise.
+	* linuxdev/drivers/scsi/NCR53c406a.c: Likewise.
+	* linuxdev/drivers/scsi/NCR53c406a.h: Likewise.
+	* linuxdev/drivers/scsi/advansys.c: Likewise.
+	* linuxdev/drivers/scsi/advansys.h: Likewise.
+	* linuxdev/drivers/scsi/aha152x.c: Likewise.
+	* linuxdev/drivers/scsi/aha152x.h: Likewise.
+	* linuxdev/drivers/scsi/aha1542.c: Likewise.
+	* linuxdev/drivers/scsi/aha1542.h: Likewise.
+	* linuxdev/drivers/scsi/aha1740.c: Likewise.
+	* linuxdev/drivers/scsi/aha1740.h: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx.c: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx.h: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx_seq.h: Likewise.
+	* linuxdev/drivers/scsi/constants.h: Likewise.
+	* linuxdev/drivers/scsi/eata.c: Likewise.
+	* linuxdev/drivers/scsi/eata.h: Likewise.
+	* linuxdev/drivers/scsi/eata_dma.c: Likewise.
+	* linuxdev/drivers/scsi/eata_dma.h: Likewise.
+	* linuxdev/drivers/scsi/eata_generic.h: Likewise.
+	* linuxdev/drivers/scsi/eata_pio.c: Likewise.
+	* linuxdev/drivers/scsi/eata_pio.h: Likewise.
+	* linuxdev/drivers/scsi/fdomain.c: Likewise.
+	* linuxdev/drivers/scsi/fdomain.h: Likewise.
+	* linuxdev/drivers/scsi/g_NCR5380.c: Likewise.
+	* linuxdev/drivers/scsi/g_NCR5380.h: Likewise.
+	* linuxdev/drivers/scsi/hosts.c: Likewise.
+	* linuxdev/drivers/scsi/hosts.h: Likewise.
+	* linuxdev/drivers/scsi/in2000.c: Likewise.
+	* linuxdev/drivers/scsi/in2000.h: Likewise.
+	* linuxdev/drivers/scsi/pas16.c: Likewise.
+	* linuxdev/drivers/scsi/pas16.h: Likewise.
+	* linuxdev/drivers/scsi/scsi.c: Likewise.
+	* linuxdev/drivers/scsi/scsi.h: Likewise.
+	* linuxdev/drivers/scsi/scsi_ioctl.c: Likewise.
+	* linuxdev/drivers/scsi/scsi_proc.c: Likewise.
+	* linuxdev/drivers/scsi/scsicam.c: Likewise.
+	* linuxdev/drivers/scsi/sd.c: Likewise.
+	* linuxdev/drivers/scsi/sd.h: Likewise.
+	* linuxdev/drivers/scsi/sd_ioctl.c: Likewise.
+	* linuxdev/drivers/scsi/seagate.c: Likewise.
+	* linuxdev/drivers/scsi/seagate.h: Likewise.
+	* linuxdev/drivers/scsi/sr.c: Likewise.
+	* linuxdev/drivers/scsi/sr_ioctl.c: Likewise.
+	* linuxdev/drivers/scsi/t128.c: Likewise.
+	* linuxdev/drivers/scsi/t128.h: Likewise.
+	* linuxdev/drivers/scsi/u14-34f.c: Likewise.
+	* linuxdev/drivers/scsi/u14-34f.h: Likewise.
+	* linuxdev/drivers/scsi/ultrastor.c: Likewise.
+	* linuxdev/drivers/scsi/ultrastor.h: Likewise.
+	* linuxdev/drivers/scsi/wd7000.c: Likewise.
+	* linuxdev/drivers/scsi/wd7000.h: Likewise.
+	* linuxdev/include/asm-i386/bitops.h: Likewise.
+	* linuxdev/include/asm-i386/delay.h: Likewise.
+	* linuxdev/include/asm-i386/dma.h: Likewise.
+	* linuxdev/include/asm-i386/errno.h: Likewise.
+	* linuxdev/include/asm-i386/fcntl.h: Likewise.
+	* linuxdev/include/asm-i386/floppy.h: Likewise.
+	* linuxdev/include/asm-i386/ioctl.h: Likewise.
+	* linuxdev/include/asm-i386/floppy.h: Likewise.
+	* linuxdev/include/asm-i386/irq.h: Likewise.
+	* linuxdev/include/asm-i386/processor.h: Likewise.
+	* linuxdev/include/asm-i386/ptrace.h: Likewise.
+	* linuxdev/include/asm-i386/resource.h: Likewise.
+	* linuxdev/include/asm-i386/segment.h: Likewise.
+	* linuxdev/include/asm-i386/sigcontext.h: Likewise.
+	* linuxdev/include/asm-i386/signal.h: Likewise.
+	* linuxdev/include/asm-i386/socket.h: Likewise.
+	* linuxdev/include/asm-i386/statfs.h: Likewise.
+	* linuxdev/include/asm-i386/string.h: Likewise.
+	* linuxdev/include/asm-i386/system.h: Likewise.
+	* linuxdev/include/asm-i386/termios.h: Likewise.
+	* linuxdev/include/asm-i386/types.h: Likewise.
+	* linuxdev/include/asm-i386/unistd.h: Likewise.
+	* linuxdev/include/linux/autoconf.h: Likewise.
+	* linuxdev/include/linux/binfmts.h: Likewise.
+	* linuxdev/include/linux/bios32.h: Likewise.
+	* linuxdev/include/linux/blk.h: Likewise.
+	* linuxdev/include/linux/blkdev.h: Likewise.
+	* linuxdev/include/linux/cdrom.h: Likewise.
+	* linuxdev/include/linux/config.h: Likewise.
+	* linuxdev/include/linux/etherdevice.h: Likewise.
+	* linuxdev/include/linux/fd.h: Likewise.
+	* linuxdev/include/linux/fdreg.h: Likewise.
+	* linuxdev/include/linux/fs.h: Likewise.
+	* linuxdev/include/linux/genhd.h: Likewise.
+	* linuxdev/include/linux/hdreg.h: Likewise.
+	* linuxdev/include/linux/if.h: Likewise.
+	* linuxdev/include/linux/if_arp.h: Likewise.
+	* linuxdev/include/linux/if_ether.h: Likewise.
+	* linuxdev/include/linux/if_tr.h: Likewise.
+	* linuxdev/include/linux/igmp.h: Likewise.
+	* linuxdev/include/linux/in.h: Likewise.
+	* linuxdev/include/linux/inet.h: Likewise.
+	* linuxdev/include/linux/interrupt.h: Likewise.
+	* linuxdev/include/linux/ioport.h: Likewise.
+	* linuxdev/include/linux/ip.h: Likewise.
+	* linuxdev/include/linux/kernel.h: Likewise.
+	* linuxdev/include/linux/locks.h: Likewise.
+	* linuxdev/include/linux/major.h: Likewise.
+	* linuxdev/include/linux/malloc.h: Likewise.
+	* linuxdev/include/linux/mc146818rtc.h: Likewise.
+	* linuxdev/include/linux/mm.h: Likewise.
+	* linuxdev/include/linux/module.h: Likewise.
+	* linuxdev/include/linux/mount.h: Likewise.
+	* linuxdev/include/linux/net.h: Likewise.
+	* linuxdev/include/linux/netdevice.h: Likewise.
+	* linuxdev/include/linux/nfs.h: Likewise.
+	* linuxdev/include/linux/notifier.h: Likewise.
+	* linuxdev/include/linux/pagemap.h: Likewise.
+	* linuxdev/include/linux/pci.h: Likewise.
+	* linuxdev/include/linux/personality.h: Likewise.
+	* linuxdev/include/linux/proc_fs.h: Likewise.
+	* linuxdev/include/linux/quota.h: Likewise.
+	* linuxdev/include/linux/route.h: Likewise.
+	* linuxdev/include/linux/sched.h: Likewise.
+	* linuxdev/include/linux/skbuff.h: Likewise.
+	* linuxdev/include/linux/socket.h: Likewise.
+	* linuxdev/include/linux/sockios.h: Likewise.
+	* linuxdev/include/linux/string.h: Likewise.
+	* linuxdev/include/linux/time.h: Likewise.
+	* linuxdev/include/linux/timer.h: Likewise.
+	* linuxdev/include/linux/tqueue.h: Likewise.
+	* linuxdev/include/linux/tty.h: Likewise.
+	* linuxdev/include/linux/types.h: Likewise.
+	* linuxdev/include/linux/uio.h: Likewise.
+	* linuxdev/include/linux/version.h: Likewise.
+	* linuxdev/include/linux/wait.h: Likewise.
+	* linuxdev/include/net/af_unix.h: Likewise.
+	* linuxdev/include/net/ax25.h: Likewise.
+	* linuxdev/include/net/ax25call.h: Likewise.
+	* linuxdev/include/net/icmp.h: Likewise.
+	* linuxdev/include/net/ip.h: Likewise.
+	* linuxdev/include/net/ip_alias.h: Likewise.
+	* linuxdev/include/net/ip_forward.h: Likewise.
+	* linuxdev/include/net/ipx.h: Likewise.
+	* linuxdev/include/net/netlink.h: Likewise.
+	* linuxdev/include/net/netrom.h: Likewise.
+	* linuxdev/include/net/nrcall.h: Likewise.
+	* linuxdev/include/net/p8022.h: Likewise.
+	* linuxdev/include/net/protocol.h: Likewise.
+	* linuxdev/include/net/psnap.h: Likewise.
+	* linuxdev/include/net/raw.h: Likewise.
+	* linuxdev/include/net/route.h: Likewise.
+	* linuxdev/include/net/sock.h: Likewise.
+	* linuxdev/include/net/tcp.h: Likewise.
+	* linuxdev/include/net/udp.h: Likewise.
+
+	* linuxdev/arch/i386/linux_soft.c: Removed.
+	* linuxdev/drivers/scsi/NCR5380.src: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx_proc.src: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx_reg.h: Likewise.
+	* linuxdev/drivers/scsi/eata_dma_proc.src: Likewise.
+	* linuxdev/drivers/scsi/eata_pio_proc.src: Likewise.
+	* linuxdev/drivers/scsi/qlogic.c: Likewise.
+	* linuxdev/drivers/scsi/qlogic.h: Likewise.
+	* linuxdev/drivers/scsi/scsi_debug.c: Likewise.
+	* linuxdev/drivers/scsi/scsi_debug.h: Likewise.
+	* linuxdev/drivers/scsi/scsi_ioctl.h: Likewise.
+	* linuxdev/include/linux/math_emu.h: Likewise.
+	* linuxdev/include/linux/minix_fs.h: Likewise.
+	* linuxdev/include/linux/minix_fs_sb.h: Likewise.
+	* linuxdev/include/linux/scsi.h: Likewise.
+	* linuxdev/include/linux/scsicam.h: Likewise.
+	* linuxdev/include/linux/vm86.h: Likewise.
+
+	* linuxdev/arch/i386/linux_ctype.c: New file.
+	* linuxdev/arch/i386/linux_lib.S: Likewise.
+	* linuxdev/arch/i386/linux_softirq.c: Likewise.
+	* linuxdev/drivers/net/3c515.c: Likewise.
+	* linuxdev/drivers/net/epic100.c: Likewise.
+	* linuxdev/drivers/net/eth82586.h: Likewise.
+	* linuxdev/drivers/net/fmv18x.c: Likewise.
+	* linuxdev/drivers/net/ne2k-pci.c: Likewise.
+	* linuxdev/drivers/net/pcnet32.c: Likewise.
+	* linuxdev/drivers/net/rtl8139.c: Likewise.
+	* linuxdev/drivers/net/smc-ultra32.c: Likewise.
+	* linuxdev/drivers/net/smc9194.c: Likewise.
+	* linuxdev/drivers/net/smc9194.h: Likewise.
+	* linuxdev/drivers/net/tlan.c: Likewise.
+	* linuxdev/drivers/net/tlan.h: Likewise.
+	* linuxdev/drivers/net/wavelan.p.h: Likewise.
+	* linuxdev/drivers/net/yellowfin.c: Likewise.
+	* linuxdev/drivers/scsi/FlashPoint.c: Likewise.
+	* linuxdev/drivers/scsi/NCR5380.c: Likewise.
+	* linuxdev/drivers/scsi/NCR5380.h: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx/scsi_message.h: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx/sequencer.h: Likewise.
+	* linuxdev/drivers/scsi/aic7xxx_proc.c: Likewise.
+	* linuxdev/drivers/scsi/dc390.h: Likewise.
+	* linuxdev/drivers/scsi/dc390w.h: Likewise.
+	* linuxdev/drivers/scsi/dtc.c: Likewise.
+	* linuxdev/drivers/scsi/dtc.h: Likewise.
+	* linuxdev/drivers/scsi/eata_dma_proc.c: Likewise.
+	* linuxdev/drivers/scsi/eata_pio_proc.c: Likewise.
+	* linuxdev/drivers/scsi/gdth.c: Likewise.
+	* linuxdev/drivers/scsi/gdth.h: Likewise.
+	* linuxdev/drivers/scsi/gdth_ioctl.h: Likewise.
+	* linuxdev/drivers/scsi/gdth_proc.c: Likewise.
+	* linuxdev/drivers/scsi/gdth_proc.h: Likewise.
+	* linuxdev/drivers/scsi/ncr53c8xx.c: Likewise.
+	* linuxdev/drivers/scsi/ncr53c8xx.h: Likewise.
+	* linuxdev/drivers/scsi/ppa.c: Likewise.
+	* linuxdev/drivers/scsi/ppa.h: Likewise.
+	* linuxdev/drivers/scsi/qlogicfas.c: Likewise.
+	* linuxdev/drivers/scsi/qlogicfas.h: Likewise.
+	* linuxdev/drivers/scsi/qlogicisp.c: Likewise.
+	* linuxdev/drivers/scsi/qlogicisp.h: Likewise.
+	* linuxdev/drivers/scsi/qlogicisp_asm.c: Likewise.
+	* linuxdev/drivers/scsi/scripts.h: Likewise.
+	* linuxdev/drivers/scsi/scsiio.c: Likewise.
+	* linuxdev/drivers/scsi/scsiiom.c: Likewise.
+	* linuxdev/drivers/scsi/tmscsim.c: Likewise.
+	* linuxdev/drivers/scsi/tmscsim.h: Likewise.
+	* linuxdev/drivers/scsi/tmscsiw.c: Likewise.
+	* linuxdev/drivers/scsi/tmscsiw.h: Likewise.
+	* linuxdev/include/asm-i386/atomic.h: Likewise.
+	* linuxdev/include/asm-i386/checksum.h: Likewise.
+	* linuxdev/include/asm-i386/ioctls.h: Likewise.
+	* linuxdev/include/asm-i386/math_emu.h: Likewise.
+	* linuxdev/include/asm-i386/posix_types.h: Likewise.
+	* linuxdev/include/asm-i386/semaphore.h: Likewise.
+	* linuxdev/include/asm-i386/sockios.h: Likewise.
+	* linuxdev/include/asm-i386/string-486.h: Likewise.
+	* linuxdev/include/asm-i386/termbits.h: Likewise.
+	* linuxdev/include/asm-i386/unaligned.h: Likewise.
+	* linuxdev/include/asm-i386/vm86.h: Likewise.
+	* linuxdev/include/linux/affs_hardblocks.h: Likewise.
+	* linuxdev/include/linux/atalk.h: Likewise.
+	* linuxdev/include/linux/ax25.h: Likewise.
+	* linuxdev/include/linux/compile.h: Likewise.
+	* linuxdev/include/linux/ctype.h: Likewise.
+	* linuxdev/include/linux/fddidevice.h: Likewise.
+	* linuxdev/include/linux/icmp.h: Likewise.
+	* linuxdev/include/linux/if_fddi.h: Likewise.
+	* linuxdev/include/linux/ipx.h: Likewise.
+	* linuxdev/include/linux/md.h: Likewise.
+	* linuxdev/include/linux/netrom.h: Likewise.
+	* linuxdev/include/linux/posix_types.h: Likewise.
+	* linuxdev/include/linux/random.h: Likewise.
+	* linuxdev/include/linux/ucdrom.h: Likewise.
+	* linuxdev/include/linux/udp.h: Likewise.
+	* linuxdev/include/linux/wireless.h: Likewise.
+	* linuxdev/include/net/br.h: Likewise.
+	* linuxdev/include/net/gc.h: Likewise.
+	* linuxdev/include/net/ip_masq.h: Likewise.
+	* linuxdev/include/net/p8022tr.h: Likewise.
+	* linuxdev/include/net/p8022trcall.h: Likewise.
+	* linuxdev/include/net/rose.h: Likewise.
+	* linuxdev/include/net/rosecall.h: Likewise.
+	* linuxdev/include/net/slhc_vj.h: Likewise.
+	* linuxdev/include/net/spx.h: Likewise.
+	* linuxdev/include/scsi/scsi.h: Likewise.
+	* linuxdev/include/scsi/scsi_ioctl.h: Likewise.
+	* linuxdev/include/scsi/scsicam.h: Likewise.
+
+1998-11-06  OKUJI Yoshinori  <okuji@kuicr.kyoto-u.ac.jp>
+
+	* i386/i386at/gpl/linux: Moved to ...
+	* linuxdev: ... here.
+	* i386/Makefrag: Linux drivers specific code moved to ...
+	* linuxdev/Makefrag: ... here.
+	* i386/Files: Recreated.
+	* i386/Subdirs: Likewise.
+	* linuxdev/drivers: New directory.
+	* linuxdev/arch: Likewise.
+	* linuxdev/arch/i386: Likewise.
+	* linuxdev/{block,scsi,net,pci}: Moved to ...
+	* linuxdev/drivers/{block,scsi,net,pci}: ... here.
+	* i386/{Drivers.in,device-drivers.h.in,driverlist.in}: Moved to ...
+	* linuxdev/{Drivers.in,device-drivers.h.in,driverlist.in}: ... here.
+	* linuxdev/{linux_emul.h,linux_*.c}: Moved to ...
+	* linuxdev/arch/i386/{linux_emul.h,linux_*.c}: ... here.
+	* linuxdev/arch/i386/linux_block.c: Include <linux_emul.h>, instead
+	of <i386at/gpl/linux/linux_emul.h>.
+	* linuxdev/arch/i386/linux_init.c: Likewise.
+	* linuxdev/arch/i386/linux_kmem.c: Likewise.
+	* linuxdev/arch/i386/linux_misc.c: Likewise.
+	* linuxdev/arch/i386/linux_net.c: Likewise.
+	* linuxdev/arch/i386/linux_sched.c: Likewise.
+	* device/ds_routines.c: Include <linuxdev/device-drivers.h>, instead
+	of <i386/device-drivers.h>.
+	* linuxdev/arch/i386/linux_init.c: Likewise.
+	* linuxdev/include/linux/autoconf.h: Likewise.
+	* Makefile.in: Include $(srcdir)/linuxdev/Makefrag.
+	* linuxdev/Drivers.in (AC_INIT): Use include/linux/autoconf.h,
+	instead of i386/i386asm.sym.
+
+1998-10-28  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* include/mach/multiboot.h: Contents were doubled.
+
+1998-10-24  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* Makefile.in (mach_machine): Don't depend on config.status, since it
+	is always newer than the symlink target.
+
+	* i386/Makefrag ($(systype)/device-drivers.h): Depend on
+	$(systype)/driverlist, and have no commands.
+
+	* configure.in (--enable-kdb): Fix help text; handle --disable-kdb.
+	Remove BUILD_CC checks and lex/yacc checks (which were for mig).
+	(installed_clib): Remove these checks.
+	(LD, NM, MIG): Use AC_CHECK_TOOL for these.
+
+	* Makefile.in (all, clean, mostlyclean, install, dist,
+	%_interface.h rule, all *mig* rules): Remove all commands, deps,
+	and rules related to mig, which is now in a separate distribution.
+
+	* Makefile.in (before-compile): Add mach/machine.
+	(mach/machine, mach_machine): New rules to make symlink so
+	#include <mach/machine/foo.h> works.
+
+	* Makefile.in (NM): New variable, substituted by configure.
+	(check-clib-routines): Use $(NM) instead of literal "nm".
+	Fix awk script to grok __ defns and weak defns of desired symbols.
+	(clib-routines.o): Use $(CC) -r -nostartfiles -nostdlib -static
+	instead of $(LD) -r.  Use -lc instead of $(installed-clib).
+	(installed-clib): Variable removed.
+
+	* i386/Makefrag: Use -include for linux-flags, so no warning.
+
+	* device/chario.c: Add forward decl for ttstart.
+
+	* i386/i386/db_trace.c: Use explicit int in decl.
+
+	* device/ds_routines.c (device_write_trap, device_writev_trap,
+	ds_trap_write_done): Cast arg to zfree.
+
+	* kern/ipc_tt.c (mach_ports_lookup): Remove unnecessary cast.
+
+1998-10-04  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* include/mach/message.h: Use __typeof instead of typeof.
+
+1998-09-06  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* kern/time_out.h: Include <mach/time_value.h> for time_value_t defn.
+
+1998-07-19  Roland McGrath  <roland@baalperazim.frob.com>
+
+	* mig: Subdirectory removed, now in separate dist.
+
+Fri Apr 24 14:24:15 1998  Thomas Bushnell, n/BSG  <tb@mit.edu>
+
+	* i386/i386/pcb.c (thread_setstatus): Set STATE before validating
+	segment registers.  Reported by UCHIYAMA Fasushi (uch@nop.or.jp).
+
+Fri Apr 24 13:19:40 1998  Thomas Bushnell n/BSG  <thomas@melange.gnu.org>
+
+	* kern/debug.c (panic): Increase "seconds" in delay to 1000; machines
+	are faster now.
+
+	* i386/i386at/gpl/linux/linux_kmem.c: Increase MEM_CHUNKS to 7.
+
+Wed Aug 20 16:05:19 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* kern/thread.h (struct thread): New member `creation_time'.
+	* include/mach/thread_info.h: New member `creation_time'.
+	* kern/thread.c (thread_create): Set creation time stamp.
+	(thread_info) [THREAD_BASIC_INFO]: Fill in new creation time
+	field.  Carefully preserve compatibility with old callers.
+
+	* kern/task.h (struct task): New member `creation_time'.
+	* include/mach/task_info.h: New member `creation_time'.
+	* kern/task.c (task_create): Set creation time stamp.
+	(task_info) [TASK_BASIC_INFO]: Fill in new creation time field.
+	Carefully preserve compatibility with old callers.
+
+	* kern/mach_clock.c (record_time_stamp): New function.
+	* kern/time_out.h (record_time_stamp): Add prototype.
+
+Sun Aug  3 18:25:38 1997  Shantanu Goel  <goel@cs.columbia.edu>
+
+	* i386/i386/thread.h (struct pcb): Added new field `data' used
+	by Linux driver emulation.
+
+	* i386/i386at/gpl/linux/include/linux/blk.h (end_request):
+	Revamped Mach specific code.  Don't use `errors' field in request.
+	Don't call driver's request function.
+
+	* i386/i386at/gpl/linux/include/linux/fs.h (struct buffer_head):
+	Deleted old Mach-specific definition.  Use original Linux defintion.
+
+	* i386/i386at/gpl/linux/linux_block.c:  Rewritten extensively.
+	(collect_buffer_pages): Deleted.
+	(alloc_buffer, free_buffer): Rewritten to use Mach page allocator.
+	(getblk, __brelse): Use Mach kernel allocator.
+	(check_for_error): Deleted.
+	(ll_rw_block): Allocate request structure on stack.
+	(rdwr_partial, rdwr_full, do_rdwr) New routines.
+	(block_read, block_write): Rewritten to use new routine do_rdwr.
+	(find_name): New routine.
+	(read_bsd_label, read_vtoc): New routines.
+	(init_partition): New routine.
+	(device_open): Rewritten for modularity.  Allocate Linux block
+	variables on the stack.
+	(check_limit): New routine.
+	(device_read, device_write): Rewritten extensively.  Map user
+	pages into kernel buffer before passing to driver.  This is in
+	preparation for general Linux block driver support.  Allocate
+	Linux block variables on the stack.
+
+	* i386/i386at/gpl/linux/linux_kmem.c:
+	(collect_buffer_pages): Deleted.
+
+Fri Aug  1 16:15:33 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* kern/mach_clock.c (clock_interrupt): Test correct macro to see
+	if PC sampling is configured: MACH_PCSAMPLE, not MACH_SAMPLE.
+
+	* i386/i386/locore.S (discover_x86_cpu_type): Comment out routine
+	for now.
+	* i386/i386at/model_dep.c (c_boot_entry): Comment out use of
+	discover_x86_cpu_type for now.
+
+	* i386/include/mach/i386/eflags.h (EFL_AC, EFL_ID): New bits.
+
+	* i386/i386/locore.S (discover_x86_cpu_type): Use correct opcode
+	for right shift.  Use ENTRY macro correctly.
+
+Mon Jul 28 17:01:19 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* COPYING: New file.
+	* Makefile.in (topfiles): Add COPYING.
+
+Mon Jul 21 14:20:39 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* kern/mach4.srv: Include <mach_pcsample.h> so the value of
+	MACH_PCSAMPLE is made available for mach4.defs.
+
+Thu Jul 10 13:51:20 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* Makefile.in (install): Use `ln -sf' instead of `-ln -s'.
+	Suggested by Marcus G. Daniels (marcus@cathcart.sysc.pdx.edu).
+
+Thu Jun 26 13:48:31 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/i386/locore.S (discover_x86_cpu_type): New function.
+	* i386/i386at/model_dep.c (c_boot_entry): Fill in cpu type in
+	MACHINE_SLOT using new function.
+
+	* include/mach/machine.h (CPU_TYPE_I486, CPU_TYPE_PENTIUM,
+	CPU_TYPE_PENTIUMPRO, CPU_TYPE_POWERPC): New CPU types.  These
+	conform to current OSF Mach values, but note that some of the
+	various subtypes are different.
+
+Mon Jun 16 12:14:17 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/i386/loose_ends.c (ovbcopy): Delete function.  Suggested by
+	Matthew Wilcox (willy@odie.barnet.ac.uk.)
+
+Thu Jun 12 18:08:29 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	Version 1.1.3 released.
+
+	* version.c (version): Update to 1.1.3.
+
+Wed Jun 11 20:16:47 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/Drivers.in: Add el3.  How did this escape notice?
+	* i386/device-drivers.h.in: Add CONFIG_EL3.
+
+Tue Jun 10 13:33:37 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	Version 1.1.2 released.
+
+	* Makefile.in (install): Install cross-migcom as `migcom', not as
+	`mig'.
+
+	* i386/Makefrag (objfiles += $(device_drivers)): Sort
+	$(device_drivers) before adding to objfiles in order to remove
+	duplicates.
+
+Mon Jun  9 22:14:09 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/Drivers.in: Fix typos apt.o -> atp.o; 3c403.o -> 3c503.o.
+
+	* Drivers.macros (AC_DRIVER): Test the class selected flag
+	correctly.
+
+Mon May 26 14:33:19 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* version.c (version): Update to version 1.1.2.
+
+Fri May 23 10:08:48 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* kern/thread.c (thread_info): Set flags word correctly;
+	TH_FLAGS_SWAPPED and TH_FLAGS_IDLE are not exclusive.
+
+	* Makefile.in (topfiles): Add aclocal.m4.
+	Reported by Marcus G. Daniels (marcus@cathcart.sysc.pdx.edu).
+
+Mon May 12 11:25:38 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	Version 1.1.1 released.
+
+	* version.c (version): Update to version 1.1.1.
+
+	* bogus/mach_kdb.h: Make sure MACH_KDB is always defined, to zero
+	if necessary.  Bug report from Marcus Daniels
+	(marcus@cathcart.sysc.pdx.edu).
+
+Fri May  9 13:06:25 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/Files: Fix typo for _setjmp.S.
+	Reflect 53c7,8xx.c -> 53c78xx.c change.
+
+Wed May  7 15:32:08 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* version.c (version): Update to version 1.1.
+	* NEWS: New file.
+	* Makefile.in (topfiles): Add NEWS.
+
+Mon May  5 11:34:01 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* Makefile.in (enable_kdb): Use findstring instead of filter.
+	Reported by Marcus Daniels (marcus@cathcart.sysc.pdx.edu).
+
+Fri May  2 12:43:46 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* Makefile.in (enable_kdb): New variable.
+	(clib-routines): If enable_kdb, then add strstr.
+	* i386/i386/_setjmp.S: New file, from UK22 libmach.
+	* i386/Files: Add i386/i386/_setjmp.S.
+	* i386/Makefrag (objfiles): Add _setjmp.o if enable_kdb.
+
+1997-04-30  Marcus G. Daniels  <marcus@cathcart.sysc.pdx.edu>
+
+	* Makefile.in (clib-routines): Add htons not because it is necessary,
+	but because libc5 systems will bring it in.
+	(check-clib-routines): Tolerate extra weak symbols.
+
+Wed Apr 30 14:12:12 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* Makefile.in: Delete duplicate rule for cross-mig.
+
+Mon Apr 28 12:09:53 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* Makefile.in (check): New target.  Reported by
+	xtest@postman.epa.go.jp.
+
+	* i386/Drivers.in (ncr53c7xx): Change file name to 53c78xx.o.
+	* i386/i386at/gpl/linux/scsi/53c7,8xx.c: Moved to ...
+	* i386/i386at/gpl/linux/scsi/53c78xx.c: ... here.
+	* i386/Makefrag (linux-scsi-files): Change file name here too.
+	Reported by xtest@postman.epa.go.jp.
+
+Wed Apr 23 14:35:44 1997  Miles Bader  <miles@gnu.ai.mit.edu>
+
+	* ipc/ipc_entry.c [MACH_KDB]: Add include of <kern/task.h>.
+
+Wed Apr 23 13:21:23 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* configure.in (BUILD_CC): Use AC_CHECK_PROGS, not AC_CHECK_PROG,
+	since we are checking multiple names.
+
+	* configure.in (kdb): New --enable option.
+	* Makefile.in (DEFINES): Add @DEFS@.
+	* bogus/mach_kdb.h: Make this file zero length; we get MACH_KDB
+	from configure now.
+
+	* Makefile.in (clean, distclean, mostlyclean, maintainter-clean):
+	New targets.
+	(all-archs-configures): New variable.
+	(MIG): Change to ./local-mig.
+	(./local-mig): Change to build this instead of ./mig
+	(check-clib-routines): Use nm -g in case there are local symbols.
+	Suggested by Matthew Wilcox (willy@odie.barnet.ac.uk).
+
+Fri Apr 18 15:25:10 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* configure.in: Add AC_PREREQ for version 2.12.
+	* i386/Drivers.in: Likewise.
+
+Wed Apr 16 16:55:36 1997  Marcus G. Daniels  <marcus@cathcart.sysc.pdx.edu>
+
+	* configure.in: Replace AC_PROG_CC with AC_PROG_CC_LOCAL.
+	If cross compiling do Lex/Yacc checks with BUILD_CC.
+        Check CC and BUILD_CC for libraries having the needed support,
+	and substitute discovery in installed_clib.
+
+	* aclocal.m4: New file.  These replacement macros are to handle
+	the case where there is a cross compiler but no supporting files.
+
+	* Makefile.in (installed-clib): Don't hardwire a Hurd libcrt.a.
+	(cross_linkable): Only define cross-migcom variable when it will
+	be possible to build it.
+	(all, install): Use $(cross-migcom).
+	(install): Install cross-migcom only if was to be built.
+	(mkinstalldirs): Add $(bindir), $(includedir)/mach/exec
+	(cross-lexxer.o lexxer.o): lexxer.o needs cpu.h.
+	(./cross-migcom): Prevent dependency generation for cross-* MiG files
+	unless they can actually be built.
+
+Thu Apr 17 15:55:40 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* kern/exception.c (exception_no_server): Comment out the suspend
+	code; it's useful for special case debugging, but causes problems
+	in general.
+
+Wed Apr 16 12:52:25 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* Makefile.in (cross-lexxer.o lexxer.o): Add pump-priming
+	dependency on cpu.h.  Reported by Marcus G. Daniels
+	(marcus@cathcart.sysc.pdx.edu).
+
+	* configure.in: Fail if configure target is not for GNU os.
+
+	* i386/Drivers.in (com): Delete option.  It's required by
+	kd_mouse.c.
+	* i386/Makefrag (i386at-files): Add com.c.
+	(driver-files): Delete variable.
+	* i386/bogus/com.h: Revert change of March 10.
+	* i386/device-drivers.h.in (CONFIG_MACH_COM): Delete option.
+	Bug report from Marcus G. Daniels (marcus@cathcart.sysc.pdx.edu).
+
+	* Makefile.in (./cross-mig): New rule.
+	(mkinstalldirs): Add $(libexecdir).
+	* configure.in: Recognize i686.
+	Reported by Marcus G. Daniels (marcus@cathcart.sysc.pdx.edu).
+
+Mon Apr 14 11:50:45 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* Released version 1.0.
+
+	* kern/exception.c (exception_no_server): Try and suspend the
+	failing thread before killing the task.  Then a debugger can be
+	used.
+
+	* i386/Makefrag: Add rebuilding rules for configure subscript.
+
+	* i386/Makefrag: Fix up copyright notice.
+	* i386/Drivers.in: Likewise.
+	* Makefile.in: Likewise.
+	* Drivers.macros: Likewise.
+	* configure.in: Likewise.
+
+	* include/sys/time.h: New file, from include/mach/sa/sys/time.h.
+	* include/sys/reboot.h: New file, from include/mach/sa/sys/reboot.h.
+	* include/sys/ioctl.h: New file, from include/mach/sa/sys/ioctl.h.
+	* include/alloca.h: New file, from include/mach/sa/alloca.h.
+	* Makefile.in (other-sys-headers): Add time.h, ioctl.h, and reboot.h.
+	(other-mach-headers): New variable.
+	(mach-exec-headers): New variable.
+	(other-headers): New variable.
+	(installed-headers): Add mach-exec-headers.
+	(dist): Distribute other-mach-headers, other-sys-headers,
+	mach-exec-headers, and other-headers.
+	(device-files): Add device.srv.
+
+	* Makefile.in (check-clib-routines): Use more efficient rule.
+
+Fri Apr 11 15:18:09 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* Makefile.in (dist): Repair rule.
+	(other-sys-headers): New variable.
+	(dist): Install $(other-sys-headers).
+	(INCLUDES): Remove -I$(srcdir)/include/mach/sa.
+	(rules for mig-related .d files): Include MiG-specific -I flags.
+	(mach-headers): Add inline.h.
+	* include/sys/types.h: New file, from include/mach/sa/sys/types.h.
+
+Mon Mar 24 16:23:21 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* version.c (version): Make that 1.0.  Whee.
+
+Fri Mar 21 15:50:09 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/i386at/gpl/linux/scsi/aha1740.c (aha1740_test_port): Try
+ 	and turn on PORTADDR_ENH before checking it.
+
+	* vm/vm_object.c (vm_object_cached_max): Increase to 200.
+
+Thu Mar 20 12:33:06 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* Makefile.in (dist): New target.  Reorganized some vars
+	describing source.
+	* i386/Subdirs: New file.
+	* i386/Files: New file.
+
+	* version.c (version): Push back to 0.1.
+
+	* Makefile.in (cross_compiling, bindir, libexecdir): New
+	variable.
+
+	* Makefile.in (install): Depend on cross-mig and cross-migcom;
+	install them.  New rules added to build mig, migcom, cross-mig,
+	and cross-migcom.
+
+	* configure.in (AC_PROG_LEX, AC_PROG_YACC): New tests.
+	(BUILD_CC): New test to set these.
+
+	* Makefile.in (%.h %_user.c): Depend on $(MIG) too.
+	(%_interface.h %_server.c): Likewise.
+	(MIG): Don't use @MIG@; hard code it to the one we build.
+	(BUILD_CC, BUILD_CFLAGS, MIGCOM, LEX, YACC, LEXLIB): New variables.
+
+Wed Mar 19 16:47:28 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/i386at/kd.c (BROKEN_KEYBOARD_RESET): Turn off this so that
+	we attempt the keyboard resets.
+	* i386/i386/locore.S (cpu_shutdown): Attempt to provide a more
+	`robust' null_idtr.
+
+Mon Mar 17 13:47:14 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/i386at/gpl/linux/scsi/hosts.c (scsi_init): Don't print out
+	gratuitious obnoxiousness.
+	* i386/i386at/gpl/linux/scsi/scsi.c (scsi_dev_init): Likewise.
+	* i386/i386at/gpl/linux/block/triton.c (ide_init_triton):
+	Likewise.
+	(init_triton_dma): Likewise.
+	* i386/i386at/gpl/linux/pci/pci.c (pci_init): Likewise.
+	* i386/i386at/gpl/linux/pci/bios32.c (check_pcibios): Likewise.
+	(pcibios_init): Likewise.
+	* i386/i386at/gpl/linux/block/genhd.c (add_partition): Likewise.
+
+	* i386/i386at/gpl/linux/net/8390.c (ei_debug): Make default value
+	zero.
+
+Wed Mar 12 14:50:46 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/i386at/com.c (comprobe): Turn off noisiness.
+
+	* i386/i386at/gpl/linux/linux_block.c (check_disk_change): Don't
+	print out gratuitous obnoxiousness.
+	(device_open): Likewise.
+	* kern/bootstrap.c (copy_bootstrap): Likewise.
+	(user_bootstrap): Likewise.
+	* i386/i386at/gpl/linux/block/genhd.c (msdos_partition): Likewise.
+	(osf_partition): Likewise.
+	(sun_partition): Likewise.
+	(check_partition): Likewise.
+	* i386/i386/pit.c (findspeed): Likewise.
+	* vm/vm_resident.c (vm_page_bootstrap): Likewise.
+
+Mon Mar 10 15:04:47 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/i386at/gpl/linux/linux_init.c (calibrate_delay): Don't
+	print out gratuitous obnoxiousness.
+
+	* i386/i386at/gpl/linux/linux_init.c (linux_init): Only call
+	linux_net_emulation_init if CONFIG_INET.  Include
+	<i386/device-drivers.h>.
+
+	* i386/i386at/i386at_ds_routines.c: Include
+	<i386/device-drivers.h>.  Don't mention linux_net_emulation_ops
+	unless CONFIG_INET.
+
+	* device/ds_routines.c (io_done_thread_continue): [i386]
+ 	Conditionalize free_skbuffs also on CONFIG_INET.  Include
+ 	<i386/device-drivers.h>.
+
+	* i386/Drivers.in, i386/device-drivers.h.in, i386/driverlist.in:
+	New files.
+	* i386/Makefrag: Include i386/driverlist; don't include all device
+	drivers in kernel image; instead use list from driverlist.
+	* configure.in: Configure in $systype subdir too.
+
+	* i386/i386at/gpl/linux/include/linux/autoconf.h: Damage severly
+	to conform to device-drivers.h model.
+
+	* i386/bogus/com.h: Include <i386/device-drivers.h>.
+	Only turn on NCOM if CONFIG_MACH_COM is present.
+
+Mon Mar  3 16:26:58 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* include/mach/message.h (__mach_msg, __mach_msg_trap): Add decls.
+
+Tue Feb 25 15:42:23 1997  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* i386/Makefrag (INCLUDES): Find `include' directory in new
+	location.
+	* Makefile (INCLUDES): Find `include' directory in new location.
+	(%.symc): Find gensym.awk in new location.
+
+	* Reorganized directories into new layout and unified mach4 and
+	mach4-i386 into a single tree.
+
+
+Older changes in ChangeLog.00 (for i386 directory) and ChangeLog.0 (for
+all other files).
diff -Npur gnumach.old/i386/Makerules.in gnumach.new/i386/Makerules.in
--- gnumach.old/i386/Makerules.in	2006-03-21 20:22:18.000000000 -0300
+++ gnumach.new/i386/Makerules.in	2006-04-05 23:07:35.000000000 -0300
@@ -28,7 +28,7 @@ include $(abs_top_builddir)/$(systype)/l
 
 
 # Some of the i386-specific code checks for these.
-DEFINES += -DCONTINUATIONS -D__ELF__ -Di386 $(DEFS-$(systype))
+DEFINES += -D__ELF__ -Di386 $(DEFS-$(systype))
 
 # Arrange for a suitable load address.
 LDFLAGS-kernel += -Ttext 100000
diff -Npur gnumach.old/i386/Makerules.in.~1.1.2.2.~ gnumach.new/i386/Makerules.in.~1.1.2.2.~
--- gnumach.old/i386/Makerules.in.~1.1.2.2.~	1969-12-31 21:00:00.000000000 -0300
+++ gnumach.new/i386/Makerules.in.~1.1.2.2.~	2006-03-21 20:22:18.000000000 -0300
@@ -0,0 +1,47 @@
+# i386/Makerules
+# Copyright 2006 Free Software Foundation, Inc.
+#
+# 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.
+#
+# THE FREE SOFTWARE FOUNDATION ALLOWS FREE USE OF THIS SOFTWARE IN ITS
+# "AS IS" CONDITION.  THE FREE SOFTWARE FOUNDATION DISCLAIMS ANY
+# LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE
+# USE OF THIS SOFTWARE.
+
+
+#
+# configure's findings.
+#
+
+DEFS-$(systype) = @DEFS@
+
+
+#
+# Glue code dependent Makerules
+#
+
+include $(abs_top_builddir)/$(systype)/linux/Makerules
+
+
+# Some of the i386-specific code checks for these.
+DEFINES += -DCONTINUATIONS -D__ELF__ -Di386 $(DEFS-$(systype))
+
+# Arrange for a suitable load address.
+LDFLAGS-kernel += -Ttext 100000
+
+# `boothdr.o' has to be at the beginning of the kernel image.
+$(systype)-objfiles-prepend = boothdr.o
+
+
+#
+# Autoconf support
+#
+
+$(abs_top_builddir)/$(systype)/Makerules: \
+  $(abs_top_srcdir)/$(systype)/Makerules.in \
+  $(abs_top_builddir)/$(systype)/config.status
+	cd $(abs_top_builddir)/$(systype) && ./config.status $(@F)
diff -Npur gnumach.old/ipc/mach_msg.c gnumach.new/ipc/mach_msg.c
--- gnumach.old/ipc/mach_msg.c	2006-03-20 08:31:36.000000000 -0300
+++ gnumach.new/ipc/mach_msg.c	2006-04-05 23:30:01.000000000 -0300
@@ -63,10 +63,6 @@
 
 extern void exception_raise_continue();
 extern void exception_raise_continue_fast();
-#ifndef CONTINUATIONS
-#define mach_msg_receive_continue	0
-#define msg_receive_continue		0
-#endif
 
 /*
  *	Routine:	mach_msg_send
@@ -198,7 +194,6 @@ mach_msg_receive(msg, option, rcv_size, 
 		return mr;
 	/* hold ref for object; mqueue is locked */
 
-#ifdef CONTINUATIONS
 	/*
 	 *	ipc_mqueue_receive may not return, because if we block
 	 *	then our kernel stack may be discarded.  So we save
@@ -212,7 +207,6 @@ mach_msg_receive(msg, option, rcv_size, 
 	self->ith_notify = notify;
 	self->ith_object = object;
 	self->ith_mqueue = mqueue;
-#endif
 
 	if (option & MACH_RCV_LARGE) {
 		mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT,
@@ -278,7 +272,6 @@ mach_msg_receive(msg, option, rcv_size, 
 	return ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
 }
 
-#ifdef CONTINUATIONS
 /*
  *	Routine:	mach_msg_receive_continue
  *	Purpose:
@@ -376,7 +369,6 @@ mach_msg_receive_continue()
 	thread_syscall_return(mr);
 	/*NOTREACHED*/
 }
-#endif /* CONTINUATIONS */
 
 /*
  *	Routine:	mach_msg_trap [mach trap]
@@ -400,7 +392,6 @@ mach_msg_trap(msg, option, send_size, rc
 {
 	mach_msg_return_t mr;
 
-#ifdef	CONTINUATIONS
 	/* first check for common cases */
 
 	if (option == (MACH_SEND_MSG|MACH_RCV_MSG)) {
@@ -1653,7 +1644,6 @@ mach_msg_trap(msg, option, send_size, rc
 		thread_syscall_return(MACH_MSG_SUCCESS);
 		/*NOTREACHED*/
 	}
-#endif	/* CONTINUATIONS */
 
 	if (option & MACH_SEND_MSG) {
 		mr = mach_msg_send(msg, option, send_size,
@@ -1672,7 +1662,6 @@ mach_msg_trap(msg, option, send_size, rc
 	return MACH_MSG_SUCCESS;
 }
 
-#ifdef CONTINUATIONS
 /*
  *	Routine:	mach_msg_continue
  *	Purpose:
@@ -1775,7 +1764,6 @@ mach_msg_interrupt(thread)
 	thread->swap_func = thread_exception_return;
 	return TRUE;
 }
-#endif /* CONTINUATIONS */
 
 #if	MACH_IPC_COMPAT
 
@@ -1947,7 +1935,6 @@ msg_receive_trap(msg, option, rcv_size, 
 		return msg_return_translate(mr);
 	/* hold ref for object; mqueue is locked */
 
-#ifdef CONTINUATIONS
 	/*
 	 *	ipc_mqueue_receive may not return, because if we block
 	 *	then our kernel stack may be discarded.  So we save
@@ -1961,7 +1948,6 @@ msg_receive_trap(msg, option, rcv_size, 
 	self->ith_timeout = (mach_msg_timeout_t) time_out;
 	self->ith_object = object;
 	self->ith_mqueue = mqueue;
-#endif /* CONTINUATIONS */
 
 	mr = ipc_mqueue_receive(mqueue,
 				(option & RCV_TIMEOUT) ?
@@ -2120,7 +2106,6 @@ msg_rpc_trap(msg, option, send_size, rcv
 	imq_lock(mqueue);
 	ip_unlock(reply);
 
-#ifdef CONTINUATIONS
 	/*
 	 *	ipc_mqueue_receive may not return, because if we block
 	 *	then our kernel stack may be discarded.  So we save
@@ -2134,7 +2119,6 @@ msg_rpc_trap(msg, option, send_size, rcv
 	self->ith_timeout = (mach_msg_timeout_t) rcv_timeout;
 	self->ith_object = (ipc_object_t) reply;
 	self->ith_mqueue = mqueue;
-#endif /* CONTINUATIONS */
 
 	mr = ipc_mqueue_receive(mqueue,
 				(option & RCV_TIMEOUT) ?
@@ -2170,7 +2154,6 @@ msg_rpc_trap(msg, option, send_size, rcv
 	return msg_return_translate(mr);
 }
 
-#ifdef CONTINUATIONS
 /*
  *	Routine:	msg_receive_continue
  *	Purpose:
@@ -2230,6 +2213,5 @@ msg_receive_continue()
 	thread_syscall_return(msg_return_translate(mr));
 	/*NOTREACHED*/
 }
-#endif /* CONTINUATIONS */
 
 #endif	/* MACH_IPC_COMPAT */
diff -Npur gnumach.old/ipc/mach_msg.c.~1.2.2.1.~ gnumach.new/ipc/mach_msg.c.~1.2.2.1.~
--- gnumach.old/ipc/mach_msg.c.~1.2.2.1.~	1969-12-31 21:00:00.000000000 -0300
+++ gnumach.new/ipc/mach_msg.c.~1.2.2.1.~	2006-03-20 08:31:36.000000000 -0300
@@ -0,0 +1,2235 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University.
+ * Copyright (c) 1993,1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL).
+ * 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, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
+ * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
+ * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
+ * THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ */
+/*
+ *	File:	ipc/mach_msg.c
+ *	Author:	Rich Draves
+ *	Date:	1989
+ *
+ *	Exported message traps.  See mach/message.h.
+ */
+
+#include <mach_ipc_compat.h>
+
+#include <mach/kern_return.h>
+#include <mach/port.h>
+#include <mach/message.h>
+#include <kern/assert.h>
+#include <kern/counters.h>
+#include <kern/lock.h>
+#include <kern/sched_prim.h>
+#include <kern/ipc_sched.h>
+#include <vm/vm_map.h>
+#include <ipc/ipc_kmsg.h>
+#include <ipc/ipc_marequest.h>
+#include <ipc/ipc_mqueue.h>
+#include <ipc/ipc_object.h>
+#include <ipc/ipc_notify.h>
+#include <ipc/ipc_port.h>
+#include <ipc/ipc_pset.h>
+#include <ipc/ipc_space.h>
+#include <ipc/ipc_thread.h>
+#include <ipc/ipc_entry.h>
+#include <ipc/mach_msg.h>
+
+
+
+extern void exception_raise_continue();
+extern void exception_raise_continue_fast();
+#ifndef CONTINUATIONS
+#define mach_msg_receive_continue	0
+#define msg_receive_continue		0
+#endif
+
+/*
+ *	Routine:	mach_msg_send
+ *	Purpose:
+ *		Send a message.
+ *	Conditions:
+ *		Nothing locked.
+ *	Returns:
+ *		MACH_MSG_SUCCESS	Sent the message.
+ *		MACH_SEND_MSG_TOO_SMALL	Message smaller than a header.
+ *		MACH_SEND_NO_BUFFER	Couldn't allocate buffer.
+ *		MACH_SEND_INVALID_DATA	Couldn't copy message data.
+ *		MACH_SEND_INVALID_HEADER
+ *			Illegal value in the message header bits.
+ *		MACH_SEND_INVALID_DEST	The space is dead.
+ *		MACH_SEND_INVALID_NOTIFY	Bad notify port.
+ *		MACH_SEND_INVALID_DEST	Can't copyin destination port.
+ *		MACH_SEND_INVALID_REPLY	Can't copyin reply port.
+ *		MACH_SEND_TIMED_OUT	Timeout expired without delivery.
+ *		MACH_SEND_INTERRUPTED	Delivery interrupted.
+ *		MACH_SEND_NO_NOTIFY	Can't allocate a msg-accepted request.
+ *		MACH_SEND_WILL_NOTIFY	Msg-accepted notif. requested.
+ *		MACH_SEND_NOTIFY_IN_PROGRESS
+ *			This space has already forced a message to this port.
+ */
+
+mach_msg_return_t
+mach_msg_send(msg, option, send_size, time_out, notify)
+	mach_msg_header_t *msg;
+	mach_msg_option_t option;
+	mach_msg_size_t send_size;
+	mach_msg_timeout_t time_out;
+	mach_port_t notify;
+{
+	ipc_space_t space = current_space();
+	vm_map_t map = current_map();
+	ipc_kmsg_t kmsg;
+	mach_msg_return_t mr;
+
+	mr = ipc_kmsg_get(msg, send_size, &kmsg);
+	if (mr != MACH_MSG_SUCCESS)
+		return mr;
+
+	if (option & MACH_SEND_CANCEL) {
+		if (notify == MACH_PORT_NULL)
+			mr = MACH_SEND_INVALID_NOTIFY;
+		else
+			mr = ipc_kmsg_copyin(kmsg, space, map, notify);
+	} else
+		mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
+	if (mr != MACH_MSG_SUCCESS) {
+		ikm_free(kmsg);
+		return mr;
+	}
+
+	if (option & MACH_SEND_NOTIFY) {
+		mr = ipc_mqueue_send(kmsg, MACH_SEND_TIMEOUT,
+				     ((option & MACH_SEND_TIMEOUT) ?
+				      time_out : MACH_MSG_TIMEOUT_NONE));
+		if (mr == MACH_SEND_TIMED_OUT) {
+			ipc_port_t dest = (ipc_port_t)
+				kmsg->ikm_header.msgh_remote_port;
+
+			if (notify == MACH_PORT_NULL)
+				mr = MACH_SEND_INVALID_NOTIFY;
+			else
+				mr = ipc_marequest_create(space, dest,
+						notify, &kmsg->ikm_marequest);
+			if (mr == MACH_MSG_SUCCESS) {
+				ipc_mqueue_send_always(kmsg);
+				return MACH_SEND_WILL_NOTIFY;
+			}
+		}
+	} else
+		mr = ipc_mqueue_send(kmsg, option & MACH_SEND_TIMEOUT,
+				     time_out);
+
+	if (mr != MACH_MSG_SUCCESS) {
+		mr |= ipc_kmsg_copyout_pseudo(kmsg, space, map);
+
+		assert(kmsg->ikm_marequest == IMAR_NULL);
+		(void) ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
+	}
+
+	return mr;
+}
+
+/*
+ *	Routine:	mach_msg_receive
+ *	Purpose:
+ *		Receive a message.
+ *	Conditions:
+ *		Nothing locked.
+ *	Returns:
+ *		MACH_MSG_SUCCESS	Received a message.
+ *		MACH_RCV_INVALID_NAME	The name doesn't denote a right,
+ *			or the denoted right is not receive or port set.
+ *		MACH_RCV_IN_SET		Receive right is a member of a set.
+ *		MACH_RCV_TOO_LARGE	Message wouldn't fit into buffer.
+ *		MACH_RCV_TIMED_OUT	Timeout expired without a message.
+ *		MACH_RCV_INTERRUPTED	Reception interrupted.
+ *		MACH_RCV_PORT_DIED	Port/set died while receiving.
+ *		MACH_RCV_PORT_CHANGED	Port moved into set while receiving.
+ *		MACH_RCV_INVALID_DATA	Couldn't copy to user buffer.
+ *		MACH_RCV_INVALID_NOTIFY	Bad notify port.
+ *		MACH_RCV_HEADER_ERROR
+ */
+
+mach_msg_return_t
+mach_msg_receive(msg, option, rcv_size, rcv_name, time_out, notify)
+	mach_msg_header_t *msg;
+	mach_msg_option_t option;
+	mach_msg_size_t rcv_size;
+	mach_port_t rcv_name;
+	mach_msg_timeout_t time_out;
+	mach_port_t notify;
+{
+	ipc_thread_t self = current_thread();
+	ipc_space_t space = current_space();
+	vm_map_t map = current_map();
+	ipc_object_t object;
+	ipc_mqueue_t mqueue;
+	ipc_kmsg_t kmsg;
+	mach_port_seqno_t seqno;
+	mach_msg_return_t mr;
+
+	mr = ipc_mqueue_copyin(space, rcv_name, &mqueue, &object);
+	if (mr != MACH_MSG_SUCCESS)
+		return mr;
+	/* hold ref for object; mqueue is locked */
+
+#ifdef CONTINUATIONS
+	/*
+	 *	ipc_mqueue_receive may not return, because if we block
+	 *	then our kernel stack may be discarded.  So we save
+	 *	state here for mach_msg_receive_continue to pick up.
+	 */
+
+	self->ith_msg = msg;
+	self->ith_option = option;
+	self->ith_rcv_size = rcv_size;
+	self->ith_timeout = time_out;
+	self->ith_notify = notify;
+	self->ith_object = object;
+	self->ith_mqueue = mqueue;
+#endif
+
+	if (option & MACH_RCV_LARGE) {
+		mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT,
+					rcv_size, time_out,
+					FALSE, mach_msg_receive_continue,
+					&kmsg, &seqno);
+		/* mqueue is unlocked */
+		ipc_object_release(object);
+		if (mr != MACH_MSG_SUCCESS) {
+			if (mr == MACH_RCV_TOO_LARGE) {
+				mach_msg_size_t real_size =
+					(mach_msg_size_t) (natural_t) kmsg;
+
+				assert(real_size > rcv_size);
+
+				(void) copyout((vm_offset_t) &real_size,
+					       (vm_offset_t) &msg->msgh_size,
+					       sizeof(mach_msg_size_t));
+			}
+
+			return mr;
+		}
+
+		kmsg->ikm_header.msgh_seqno = seqno;
+		assert(kmsg->ikm_header.msgh_size <= rcv_size);
+	} else {
+		mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT,
+					MACH_MSG_SIZE_MAX, time_out,
+					FALSE, mach_msg_receive_continue,
+					&kmsg, &seqno);
+		/* mqueue is unlocked */
+		ipc_object_release(object);
+		if (mr != MACH_MSG_SUCCESS)
+			return mr;
+
+		kmsg->ikm_header.msgh_seqno = seqno;
+		if (kmsg->ikm_header.msgh_size > rcv_size) {
+			ipc_kmsg_copyout_dest(kmsg, space);
+			(void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
+			return MACH_RCV_TOO_LARGE;
+		}
+	}
+
+	if (option & MACH_RCV_NOTIFY) {
+		if (notify == MACH_PORT_NULL)
+			mr = MACH_RCV_INVALID_NOTIFY;
+		else
+			mr = ipc_kmsg_copyout(kmsg, space, map, notify);
+	} else
+		mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
+	if (mr != MACH_MSG_SUCCESS) {
+		if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
+			(void) ipc_kmsg_put(msg, kmsg,
+					    kmsg->ikm_header.msgh_size);
+		} else {
+			ipc_kmsg_copyout_dest(kmsg, space);
+			(void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
+		}
+
+		return mr;
+	}
+
+	return ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
+}
+
+#ifdef CONTINUATIONS
+/*
+ *	Routine:	mach_msg_receive_continue
+ *	Purpose:
+ *		Continue after blocking for a message.
+ *	Conditions:
+ *		Nothing locked.  We are running on a new kernel stack,
+ *		with the receive state saved in the thread.  From here
+ *		control goes back to user space.
+ */
+
+void
+mach_msg_receive_continue()
+{
+	ipc_thread_t self = current_thread();
+	ipc_space_t space = current_space();
+	vm_map_t map = current_map();
+	mach_msg_header_t *msg = self->ith_msg;
+	mach_msg_option_t option = self->ith_option;
+	mach_msg_size_t rcv_size = self->ith_rcv_size;
+	mach_msg_timeout_t time_out = self->ith_timeout;
+	mach_port_t notify = self->ith_notify;
+	ipc_object_t object = self->ith_object;
+	ipc_mqueue_t mqueue = self->ith_mqueue;
+	ipc_kmsg_t kmsg;
+	mach_port_seqno_t seqno;
+	mach_msg_return_t mr;
+
+	if (option & MACH_RCV_LARGE) {
+		mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT,
+					rcv_size, time_out,
+					TRUE, mach_msg_receive_continue,
+					&kmsg, &seqno);
+		/* mqueue is unlocked */
+		ipc_object_release(object);
+		if (mr != MACH_MSG_SUCCESS) {
+			if (mr == MACH_RCV_TOO_LARGE) {
+				mach_msg_size_t real_size =
+					(mach_msg_size_t) (natural_t) kmsg;
+
+				assert(real_size > rcv_size);
+
+				(void) copyout((vm_offset_t) &real_size,
+					       (vm_offset_t) &msg->msgh_size,
+					       sizeof(mach_msg_size_t));
+			}
+
+			thread_syscall_return(mr);
+			/*NOTREACHED*/
+		}
+
+		kmsg->ikm_header.msgh_seqno = seqno;
+		assert(kmsg->ikm_header.msgh_size <= rcv_size);
+	} else {
+		mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT,
+					MACH_MSG_SIZE_MAX, time_out,
+					TRUE, mach_msg_receive_continue,
+					&kmsg, &seqno);
+		/* mqueue is unlocked */
+		ipc_object_release(object);
+		if (mr != MACH_MSG_SUCCESS) {
+			thread_syscall_return(mr);
+			/*NOTREACHED*/
+		}
+
+		kmsg->ikm_header.msgh_seqno = seqno;
+		if (kmsg->ikm_header.msgh_size > rcv_size) {
+			ipc_kmsg_copyout_dest(kmsg, space);
+			(void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
+			thread_syscall_return(MACH_RCV_TOO_LARGE);
+			/*NOTREACHED*/
+		}
+	}
+
+	if (option & MACH_RCV_NOTIFY) {
+		if (notify == MACH_PORT_NULL)
+			mr = MACH_RCV_INVALID_NOTIFY;
+		else
+			mr = ipc_kmsg_copyout(kmsg, space, map, notify);
+	} else
+		mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
+	if (mr != MACH_MSG_SUCCESS) {
+		if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
+			(void) ipc_kmsg_put(msg, kmsg,
+					    kmsg->ikm_header.msgh_size);
+		} else {
+			ipc_kmsg_copyout_dest(kmsg, space);
+			(void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
+		}
+
+		thread_syscall_return(mr);
+		/*NOTREACHED*/
+	}
+
+	mr = ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
+	thread_syscall_return(mr);
+	/*NOTREACHED*/
+}
+#endif /* CONTINUATIONS */
+
+/*
+ *	Routine:	mach_msg_trap [mach trap]
+ *	Purpose:
+ *		Possibly send a message; possibly receive a message.
+ *	Conditions:
+ *		Nothing locked.
+ *	Returns:
+ *		All of mach_msg_send and mach_msg_receive error codes.
+ */
+
+mach_msg_return_t
+mach_msg_trap(msg, option, send_size, rcv_size, rcv_name, time_out, notify)
+	mach_msg_header_t *msg;
+	mach_msg_option_t option;
+	mach_msg_size_t send_size;
+	mach_msg_size_t rcv_size;
+	mach_port_t rcv_name;
+	mach_msg_timeout_t time_out;
+	mach_port_t notify;
+{
+	mach_msg_return_t mr;
+
+#ifdef	CONTINUATIONS
+	/* first check for common cases */
+
+	if (option == (MACH_SEND_MSG|MACH_RCV_MSG)) {
+		register ipc_thread_t self = current_thread();
+		ipc_space_t space = self->task->itk_space;
+		register ipc_kmsg_t kmsg;
+		register ipc_port_t dest_port;
+		ipc_object_t rcv_object;
+		register ipc_mqueue_t rcv_mqueue;
+		mach_msg_size_t reply_size;
+
+		/*
+		 *	This case is divided into ten sections, each
+		 *	with a label.  There are five optimized
+		 *	sections and six unoptimized sections, which
+		 *	do the same thing but handle all possible
+		 *	cases and are slower.
+		 *
+		 *	The five sections for an RPC are
+		 *	    1) Get request message into a buffer.
+		 *		(fast_get or slow_get)
+		 *	    2) Copyin request message and rcv_name.
+		 *		(fast_copyin or slow_copyin)
+		 *	    3) Enqueue request and dequeue reply.
+		 *		(fast_send_receive or
+		 *		 slow_send and slow_receive)
+		 *	    4) Copyout reply message.
+		 *		(fast_copyout or slow_copyout)
+		 *	    5) Put reply message to user's buffer.
+		 *		(fast_put or slow_put)
+		 *
+		 *	Keep the locking hierarchy firmly in mind.
+		 *	(First spaces, then ports, then port sets,
+		 *	then message queues.)  Only a non-blocking
+		 *	attempt can be made to acquire locks out of
+		 *	order, or acquire two locks on the same level.
+		 *	Acquiring two locks on the same level will
+		 *	fail if the objects are really the same,
+		 *	unless simple locking is disabled.  This is OK,
+		 *	because then the extra unlock does nothing.
+		 *
+		 *	There are two major reasons these RPCs can't use
+		 *	ipc_thread_switch, and use slow_send/slow_receive:
+		 *		1) Kernel RPCs.
+		 *		2) Servers fall behind clients, so
+		 *		client doesn't find a blocked server thread and
+		 *		server finds waiting messages and can't block.
+		 */
+
+	/*
+	    fast_get:
+	*/
+		/*
+		 *	optimized ipc_kmsg_get
+		 *
+		 *	No locks, references, or messages held.
+		 *	We must clear ikm_cache before copyinmsg.
+		 */
+
+		if ((send_size > IKM_SAVED_MSG_SIZE) ||
+		    (send_size < sizeof(mach_msg_header_t)) ||
+		    (send_size & 3) ||
+		    ((kmsg = ikm_cache()) == IKM_NULL))
+			goto slow_get;
+
+		ikm_cache() = IKM_NULL;
+		ikm_check_initialized(kmsg, IKM_SAVED_KMSG_SIZE);
+
+		if (copyinmsg((vm_offset_t) msg, (vm_offset_t) &kmsg->ikm_header,
+			      send_size)) {
+			ikm_free(kmsg);
+			goto slow_get;
+		}
+
+		kmsg->ikm_header.msgh_size = send_size;
+
+	    fast_copyin:
+		/*
+		 *	optimized ipc_kmsg_copyin/ipc_mqueue_copyin
+		 *
+		 *	We have the request message data in kmsg.
+		 *	Must still do copyin, send, receive, etc.
+		 *
+		 *	If the message isn't simple, we can't combine
+		 *	ipc_kmsg_copyin_header and ipc_mqueue_copyin,
+		 *	because copyin of the message body might
+		 *	affect rcv_name.
+		 */
+
+		switch (kmsg->ikm_header.msgh_bits) {
+		    case MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,
+					MACH_MSG_TYPE_MAKE_SEND_ONCE): {
+			register ipc_entry_t table;
+			register ipc_entry_num_t size;
+			register ipc_port_t reply_port;
+
+			/* sending a request message */
+
+		    {
+			register mach_port_index_t index;
+			register mach_port_gen_t gen;
+
+		    {
+			register mach_port_t reply_name =
+				kmsg->ikm_header.msgh_local_port;
+
+			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;
+
+		    {
+			register ipc_entry_t entry;
+			register 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))
+				goto abort_request_copyin;
+
+			reply_port = (ipc_port_t) entry->ie_object;
+			assert(reply_port != IP_NULL);
+		    }
+		    }
+
+			/* optimized ipc_entry_lookup of dest_name */
+
+		    {
+			register mach_port_index_t index;
+			register mach_port_gen_t gen;
+
+		    {
+			register 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;
+
+		    {
+			register ipc_entry_t entry;
+			register 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_SEND)) !=
+			    (gen | MACH_PORT_TYPE_SEND))
+				goto abort_request_copyin;
+
+			assert(IE_BITS_UREFS(bits) > 0);
+
+			dest_port = (ipc_port_t) entry->ie_object;
+			assert(dest_port != IP_NULL);
+		    }
+		    }
+
+			/*
+			 *	To do an atomic copyin, need simultaneous
+			 *	locks on both ports and the space.  If
+			 *	dest_port == reply_port, and simple locking is
+			 *	enabled, then we will abort.  Otherwise it's
+			 *	OK to unlock twice.
+			 */
+
+			ip_lock(dest_port);
+			if (!ip_active(dest_port) ||
+			    !ip_lock_try(reply_port)) {
+				ip_unlock(dest_port);
+				goto abort_request_copyin;
+			}
+			is_read_unlock(space);
+
+			assert(dest_port->ip_srights > 0);
+			dest_port->ip_srights++;
+			ip_reference(dest_port);
+
+			assert(ip_active(reply_port));
+			assert(reply_port->ip_receiver_name ==
+			       kmsg->ikm_header.msgh_local_port);
+			assert(reply_port->ip_receiver == space);
+
+			reply_port->ip_sorights++;
+			ip_reference(reply_port);
+
+			kmsg->ikm_header.msgh_bits =
+				MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND,
+					       MACH_MSG_TYPE_PORT_SEND_ONCE);
+			kmsg->ikm_header.msgh_remote_port =
+					(mach_port_t) dest_port;
+			kmsg->ikm_header.msgh_local_port =
+					(mach_port_t) reply_port;
+
+			/* make sure we can queue to the destination */
+
+			if (dest_port->ip_receiver == ipc_space_kernel) {
+				/*
+				 * The kernel server has a reference to
+				 * the reply port, which it hands back
+				 * to us in the reply message.  We do
+				 * not need to keep another reference to
+				 * it.
+				 */
+				ip_unlock(reply_port);
+
+				assert(ip_active(dest_port));
+				ip_unlock(dest_port);
+				goto kernel_send;
+			}
+
+			if (dest_port->ip_msgcount >= dest_port->ip_qlimit)
+				goto abort_request_send_receive;
+
+			/* optimized ipc_mqueue_copyin */
+
+			if (reply_port->ip_pset != IPS_NULL)
+				goto abort_request_send_receive;
+
+			rcv_object = (ipc_object_t) reply_port;
+			io_reference(rcv_object);
+			rcv_mqueue = &reply_port->ip_messages;
+			imq_lock(rcv_mqueue);
+			io_unlock(rcv_object);
+			goto fast_send_receive;
+
+		    abort_request_copyin:
+			is_read_unlock(space);
+			goto slow_copyin;
+
+		    abort_request_send_receive:
+			ip_unlock(dest_port);
+			ip_unlock(reply_port);
+			goto slow_send;
+		    }
+
+		    case MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0): {
+			register ipc_entry_num_t size;
+			register ipc_entry_t table;
+
+			/* sending a reply message */
+
+		    {
+			register mach_port_t reply_name =
+				kmsg->ikm_header.msgh_local_port;
+
+			if (reply_name != MACH_PORT_NULL)
+				goto slow_copyin;
+		    }
+
+			is_write_lock(space);
+			assert(space->is_active);
+
+			/* optimized ipc_entry_lookup */
+
+			size = space->is_table_size;
+			table = space->is_table;
+
+		    {
+			register ipc_entry_t entry;
+			register mach_port_gen_t gen;
+			register mach_port_index_t index;
+
+		    {
+			register 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_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))
+				goto abort_reply_dest_copyin;
+
+			/* optimized ipc_right_copyin */
+
+			assert(IE_BITS_TYPE(entry->ie_bits) ==
+						MACH_PORT_TYPE_SEND_ONCE);
+			assert(IE_BITS_UREFS(entry->ie_bits) == 1);
+			assert((entry->ie_bits & IE_BITS_MAREQUEST) == 0);
+
+			if (entry->ie_request != 0)
+				goto abort_reply_dest_copyin;
+
+			dest_port = (ipc_port_t) entry->ie_object;
+			assert(dest_port != IP_NULL);
+
+			ip_lock(dest_port);
+			if (!ip_active(dest_port)) {
+				ip_unlock(dest_port);
+				goto abort_reply_dest_copyin;
+			}
+
+			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;
+		    }
+
+			kmsg->ikm_header.msgh_bits =
+				MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE,
+					       0);
+			kmsg->ikm_header.msgh_remote_port =
+					(mach_port_t) dest_port;
+
+			/* make sure we can queue to the destination */
+
+			assert(dest_port->ip_receiver != ipc_space_kernel);
+
+			/* optimized ipc_entry_lookup/ipc_mqueue_copyin */
+
+		    {
+			register ipc_entry_t entry;
+			register ipc_entry_bits_t bits;
+
+		    {
+			register mach_port_index_t index;
+			register mach_port_gen_t gen;
+
+			index = MACH_PORT_INDEX(rcv_name);
+			gen = MACH_PORT_GEN(rcv_name);
+
+			if (index >= size)
+				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) {
+				register ipc_pset_t rcv_pset;
+
+				rcv_pset = (ipc_pset_t) entry->ie_object;
+				assert(rcv_pset != IPS_NULL);
+
+				ips_lock(rcv_pset);
+				assert(ips_active(rcv_pset));
+
+				rcv_object = (ipc_object_t) rcv_pset;
+				rcv_mqueue = &rcv_pset->ips_messages;
+			} else if (bits & MACH_PORT_TYPE_RECEIVE) {
+				register ipc_port_t rcv_port;
+
+				rcv_port = (ipc_port_t) entry->ie_object;
+				assert(rcv_port != IP_NULL);
+
+				if (!ip_lock_try(rcv_port))
+					goto abort_reply_rcv_copyin;
+				assert(ip_active(rcv_port));
+
+				if (rcv_port->ip_pset != IPS_NULL) {
+					ip_unlock(rcv_port);
+					goto abort_reply_rcv_copyin;
+				}
+
+				rcv_object = (ipc_object_t) rcv_port;
+				rcv_mqueue = &rcv_port->ip_messages;
+			} else
+				goto abort_reply_rcv_copyin;
+		    }
+
+			is_write_unlock(space);
+			io_reference(rcv_object);
+			imq_lock(rcv_mqueue);
+			io_unlock(rcv_object);
+			goto fast_send_receive;
+
+		    abort_reply_dest_copyin:
+			is_write_unlock(space);
+			goto slow_copyin;
+
+		    abort_reply_rcv_copyin:
+			ip_unlock(dest_port);
+			is_write_unlock(space);
+			goto slow_send;
+		    }
+
+		    default:
+			goto slow_copyin;
+		}
+		/*NOTREACHED*/
+
+	    fast_send_receive:
+		/*
+		 *	optimized ipc_mqueue_send/ipc_mqueue_receive
+		 *
+		 *	Finished get/copyin of kmsg and copyin of rcv_name.
+		 *	space is unlocked, dest_port is locked,
+		 *	we can queue kmsg to dest_port,
+		 *	rcv_mqueue is locked, rcv_object holds a ref,
+		 *	if rcv_object is a port it isn't in a port set
+		 *
+		 *	Note that if simple locking is turned off,
+		 *	then we could have dest_mqueue == rcv_mqueue
+		 *	and not abort when we try to lock dest_mqueue.
+		 */
+
+		assert(ip_active(dest_port));
+		assert(dest_port->ip_receiver != ipc_space_kernel);
+		assert((dest_port->ip_msgcount < dest_port->ip_qlimit) ||
+		       (MACH_MSGH_BITS_REMOTE(kmsg->ikm_header.msgh_bits) ==
+						MACH_MSG_TYPE_PORT_SEND_ONCE));
+		assert((kmsg->ikm_header.msgh_bits &
+						MACH_MSGH_BITS_CIRCULAR) == 0);
+
+	    {
+		register ipc_mqueue_t dest_mqueue;
+		register ipc_thread_t receiver;
+
+	    {
+		register ipc_pset_t dest_pset;
+
+		dest_pset = dest_port->ip_pset;
+		if (dest_pset == IPS_NULL)
+			dest_mqueue = &dest_port->ip_messages;
+		else
+			dest_mqueue = &dest_pset->ips_messages;
+	    }
+
+		if (!imq_lock_try(dest_mqueue)) {
+		    abort_send_receive:
+			ip_unlock(dest_port);
+			imq_unlock(rcv_mqueue);
+			ipc_object_release(rcv_object);
+			goto slow_send;
+		}
+
+		receiver = ipc_thread_queue_first(&dest_mqueue->imq_threads);
+		if ((receiver == ITH_NULL) ||
+		    (ipc_kmsg_queue_first(&rcv_mqueue->imq_messages)
+								!= IKM_NULL)) {
+			imq_unlock(dest_mqueue);
+			goto abort_send_receive;
+		}
+
+		/*
+		 *	There is a receiver thread waiting, and
+		 *	there is no reply message for us to pick up.
+		 *	We have hope of hand-off, so save state.
+		 */
+
+		self->ith_msg = msg;
+		self->ith_rcv_size = rcv_size;
+		self->ith_object = rcv_object;
+		self->ith_mqueue = rcv_mqueue;
+
+		if ((receiver->swap_func == (void (*)()) mach_msg_continue) &&
+		    thread_handoff(self, mach_msg_continue, receiver)) {
+			assert(current_thread() == receiver);
+
+			/*
+			 *	We can use the optimized receive code,
+			 *	because the receiver is using no options.
+			 */
+		} else if ((receiver->swap_func ==
+				(void (*)()) exception_raise_continue) &&
+			   thread_handoff(self, mach_msg_continue, receiver)) {
+			counter(c_mach_msg_trap_block_exc++);
+			assert(current_thread() == receiver);
+
+			/*
+			 *	We are a reply message coming back through
+			 *	the optimized exception-handling path.
+			 *	Finish with rcv_mqueue and dest_mqueue,
+			 *	and then jump to exception code with
+			 *	dest_port still locked.  We don't bother
+			 *	with a sequence number in this case.
+			 */
+
+			ipc_thread_enqueue_macro(
+				&rcv_mqueue->imq_threads, self);
+			self->ith_state = MACH_RCV_IN_PROGRESS;
+			self->ith_msize = MACH_MSG_SIZE_MAX;
+			imq_unlock(rcv_mqueue);
+
+			ipc_thread_rmqueue_first_macro(
+				&dest_mqueue->imq_threads, receiver);
+			imq_unlock(dest_mqueue);
+
+			exception_raise_continue_fast(dest_port, kmsg);
+			/*NOTREACHED*/
+			return MACH_MSG_SUCCESS;
+		} else if ((send_size <= receiver->ith_msize) &&
+			   thread_handoff(self, mach_msg_continue, receiver)) {
+			assert(current_thread() == receiver);
+
+			if ((receiver->swap_func ==
+				(void (*)()) mach_msg_receive_continue) &&
+			    ((receiver->ith_option & MACH_RCV_NOTIFY) == 0)) {
+				/*
+				 *	We can still use the optimized code.
+				 */
+			} else {
+				counter(c_mach_msg_trap_block_slow++);
+				/*
+				 *	We are running as the receiver,
+				 *	but we can't use the optimized code.
+				 *	Finish send/receive processing.
+				 */
+
+				dest_port->ip_msgcount++;
+				ip_unlock(dest_port);
+
+				ipc_thread_enqueue_macro(
+					&rcv_mqueue->imq_threads, self);
+				self->ith_state = MACH_RCV_IN_PROGRESS;
+				self->ith_msize = MACH_MSG_SIZE_MAX;
+				imq_unlock(rcv_mqueue);
+
+				ipc_thread_rmqueue_first_macro(
+					&dest_mqueue->imq_threads, receiver);
+				receiver->ith_state = MACH_MSG_SUCCESS;
+				receiver->ith_kmsg = kmsg;
+				receiver->ith_seqno = dest_port->ip_seqno++;
+				imq_unlock(dest_mqueue);
+
+				/*
+				 *	Call the receiver's continuation.
+				 */
+
+				receiver->wait_result = THREAD_AWAKENED;
+				(*receiver->swap_func)();
+				/*NOTREACHED*/
+				return MACH_MSG_SUCCESS;
+			}
+		} else {
+			/*
+			 *	The receiver can't accept the message,
+			 *	or we can't switch to the receiver.
+			 */
+
+			imq_unlock(dest_mqueue);
+			goto abort_send_receive;
+		}
+		counter(c_mach_msg_trap_block_fast++);
+
+		/*
+		 *	Safe to unlock dest_port now that we are
+		 *	committed to this path, because we hold
+		 *	dest_mqueue locked.  We never bother changing
+		 *	dest_port->ip_msgcount.
+		 */
+
+		ip_unlock(dest_port);
+
+		/*
+		 *	We need to finish preparing self for its
+		 *	time asleep in rcv_mqueue.
+		 */
+
+		ipc_thread_enqueue_macro(&rcv_mqueue->imq_threads, self);
+		self->ith_state = MACH_RCV_IN_PROGRESS;
+		self->ith_msize = MACH_MSG_SIZE_MAX;
+		imq_unlock(rcv_mqueue);
+
+		/*
+		 *	Finish extracting receiver from dest_mqueue.
+		 */
+
+		ipc_thread_rmqueue_first_macro(
+			&dest_mqueue->imq_threads, receiver);
+		kmsg->ikm_header.msgh_seqno = dest_port->ip_seqno++;
+		imq_unlock(dest_mqueue);
+
+		/*
+		 *	We don't have to do any post-dequeue processing of
+		 *	the message.  We never incremented ip_msgcount, we
+		 *	know it has no msg-accepted request, and blocked
+		 *	senders aren't a worry because we found the port
+		 *	with a receiver waiting.
+		 */
+
+		self = receiver;
+		space = self->task->itk_space;
+
+		msg = self->ith_msg;
+		rcv_size = self->ith_rcv_size;
+		rcv_object = self->ith_object;
+
+		/* inline ipc_object_release */
+		io_lock(rcv_object);
+		io_release(rcv_object);
+		io_check_unlock(rcv_object);
+	    }
+
+	    fast_copyout:
+		/*
+		 *	Nothing locked and no references held, except
+		 *	we have kmsg with msgh_seqno filled in.  Must
+		 *	still check against rcv_size and do
+		 *	ipc_kmsg_copyout/ipc_kmsg_put.
+		 */
+
+		assert((ipc_port_t) kmsg->ikm_header.msgh_remote_port
+						== dest_port);
+
+		reply_size = kmsg->ikm_header.msgh_size;
+		if (rcv_size < reply_size)
+			goto slow_copyout;
+
+		/* optimized ipc_kmsg_copyout/ipc_kmsg_copyout_header */
+
+		switch (kmsg->ikm_header.msgh_bits) {
+		    case MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND,
+					MACH_MSG_TYPE_PORT_SEND_ONCE): {
+			ipc_port_t reply_port =
+				(ipc_port_t) kmsg->ikm_header.msgh_local_port;
+			mach_port_t dest_name, reply_name;
+
+			/* receiving a request message */
+
+			if (!IP_VALID(reply_port))
+				goto slow_copyout;
+
+			is_write_lock(space);
+			assert(space->is_active);
+
+			/*
+			 *	To do an atomic copyout, need simultaneous
+			 *	locks on both ports and the space.  If
+			 *	dest_port == reply_port, and simple locking is
+			 *	enabled, then we will abort.  Otherwise it's
+			 *	OK to unlock twice.
+			 */
+
+			ip_lock(dest_port);
+			if (!ip_active(dest_port) ||
+			    !ip_lock_try(reply_port))
+				goto abort_request_copyout;
+
+			if (!ip_active(reply_port)) {
+				ip_unlock(reply_port);
+				goto abort_request_copyout;
+			}
+
+			assert(reply_port->ip_sorights > 0);
+			ip_unlock(reply_port);
+
+		    {
+			register ipc_entry_t table;
+			register ipc_entry_t entry;
+			register mach_port_index_t index;
+
+			/* optimized ipc_entry_get */
+
+			table = space->is_table;
+			index = table->ie_next;
+
+			if (index == 0)
+				goto abort_request_copyout;
+
+			entry = &table[index];
+			table->ie_next = entry->ie_next;
+			entry->ie_request = 0;
+
+		    {
+			register mach_port_gen_t gen;
+
+			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);
+		    }
+
+			assert(MACH_PORT_VALID(reply_name));
+			entry->ie_object = (ipc_object_t) reply_port;
+			is_write_unlock(space);
+		    }
+
+			/* optimized ipc_object_copyout_dest */
+
+			assert(dest_port->ip_srights > 0);
+			ip_release(dest_port);
+
+			if (dest_port->ip_receiver == space)
+				dest_name = dest_port->ip_receiver_name;
+			else
+				dest_name = MACH_PORT_NULL;
+
+			if ((--dest_port->ip_srights == 0) &&
+			    (dest_port->ip_nsrequest != IP_NULL)) {
+				ipc_port_t nsrequest;
+				mach_port_mscount_t mscount;
+
+				/* a rather rare case */
+
+				nsrequest = dest_port->ip_nsrequest;
+				mscount = dest_port->ip_mscount;
+				dest_port->ip_nsrequest = IP_NULL;
+				ip_unlock(dest_port);
+
+				ipc_notify_no_senders(nsrequest, mscount);
+			} else
+				ip_unlock(dest_port);
+
+			kmsg->ikm_header.msgh_bits =
+				MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE,
+					       MACH_MSG_TYPE_PORT_SEND);
+			kmsg->ikm_header.msgh_remote_port = reply_name;
+			kmsg->ikm_header.msgh_local_port = dest_name;
+			goto fast_put;
+
+		    abort_request_copyout:
+			ip_unlock(dest_port);
+			is_write_unlock(space);
+			goto slow_copyout;
+		    }
+
+		    case MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0): {
+			register mach_port_t dest_name;
+
+			/* receiving a reply message */
+
+			ip_lock(dest_port);
+			if (!ip_active(dest_port))
+				goto slow_copyout;
+
+			/* optimized ipc_object_copyout_dest */
+
+			assert(dest_port->ip_sorights > 0);
+
+			if (dest_port->ip_receiver == space) {
+				ip_release(dest_port);
+				dest_port->ip_sorights--;
+				dest_name = dest_port->ip_receiver_name;
+				ip_unlock(dest_port);
+			} else {
+				ip_unlock(dest_port);
+
+				ipc_notify_send_once(dest_port);
+				dest_name = MACH_PORT_NULL;
+			}
+
+			kmsg->ikm_header.msgh_bits =
+				MACH_MSGH_BITS(0,
+					       MACH_MSG_TYPE_PORT_SEND_ONCE);
+			kmsg->ikm_header.msgh_remote_port = MACH_PORT_NULL;
+			kmsg->ikm_header.msgh_local_port = dest_name;
+			goto fast_put;
+		    }
+
+		    case MACH_MSGH_BITS_COMPLEX|
+			 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0): {
+			register mach_port_t dest_name;
+
+			/* receiving a complex reply message */
+
+			ip_lock(dest_port);
+			if (!ip_active(dest_port))
+				goto slow_copyout;
+
+			/* optimized ipc_object_copyout_dest */
+
+			assert(dest_port->ip_sorights > 0);
+
+			if (dest_port->ip_receiver == space) {
+				ip_release(dest_port);
+				dest_port->ip_sorights--;
+				dest_name = dest_port->ip_receiver_name;
+				ip_unlock(dest_port);
+			} else {
+				ip_unlock(dest_port);
+
+				ipc_notify_send_once(dest_port);
+				dest_name = MACH_PORT_NULL;
+			}
+
+			kmsg->ikm_header.msgh_bits =
+				MACH_MSGH_BITS_COMPLEX |
+				MACH_MSGH_BITS(0,
+					       MACH_MSG_TYPE_PORT_SEND_ONCE);
+			kmsg->ikm_header.msgh_remote_port = MACH_PORT_NULL;
+			kmsg->ikm_header.msgh_local_port = dest_name;
+
+			mr = ipc_kmsg_copyout_body(
+				(vm_offset_t) (&kmsg->ikm_header + 1),
+				(vm_offset_t) &kmsg->ikm_header
+					+ kmsg->ikm_header.msgh_size,
+				space,
+				current_map());
+
+			if (mr != MACH_MSG_SUCCESS) {
+				(void) ipc_kmsg_put(msg, kmsg,
+					kmsg->ikm_header.msgh_size);
+				return mr | MACH_RCV_BODY_ERROR;
+			}
+			goto fast_put;
+		    }
+
+		    default:
+			goto slow_copyout;
+		}
+		/*NOTREACHED*/
+
+	    fast_put:
+		/*
+		 *	We have the reply message data in kmsg,
+		 *	and the reply message size in reply_size.
+		 *	Just need to copy it out to the user and free kmsg.
+		 *	We must check ikm_cache after copyoutmsg.
+		 */
+
+		ikm_check_initialized(kmsg, kmsg->ikm_size);
+
+		if ((kmsg->ikm_size != IKM_SAVED_KMSG_SIZE) ||
+		    copyoutmsg((vm_offset_t) &kmsg->ikm_header, (vm_offset_t) msg,
+			       reply_size) ||
+		    (ikm_cache() != IKM_NULL))
+			goto slow_put;
+
+		ikm_cache() = kmsg;
+		thread_syscall_return(MACH_MSG_SUCCESS);
+		/*NOTREACHED*/
+		return MACH_MSG_SUCCESS; /* help for the compiler */
+
+		/*
+		 *	The slow path has a few non-register temporary
+		 *	variables used only for call-by-reference.
+		 */
+
+	    {
+		ipc_kmsg_t temp_kmsg;
+		mach_port_seqno_t temp_seqno;
+		ipc_object_t temp_rcv_object;
+		ipc_mqueue_t temp_rcv_mqueue;
+
+	    slow_get:
+		/*
+		 *	No locks, references, or messages held.
+		 *	Still have to get the request, send it,
+		 *	receive reply, etc.
+		 */
+
+		mr = ipc_kmsg_get(msg, send_size, &temp_kmsg);
+		if (mr != MACH_MSG_SUCCESS) {
+			thread_syscall_return(mr);
+			/*NOTREACHED*/
+		}
+		kmsg = temp_kmsg;
+
+		/* try to get back on optimized path */
+		goto fast_copyin;
+
+	    slow_copyin:
+		/*
+		 *	We have the message data in kmsg, but
+		 *	we still need to copyin, send it,
+		 *	receive a reply, and do copyout.
+		 */
+
+		mr = ipc_kmsg_copyin(kmsg, space, current_map(),
+				     MACH_PORT_NULL);
+		if (mr != MACH_MSG_SUCCESS) {
+			ikm_free(kmsg);
+			thread_syscall_return(mr);
+			/*NOTREACHED*/
+		}
+
+		/* try to get back on optimized path */
+
+		if (kmsg->ikm_header.msgh_bits & MACH_MSGH_BITS_CIRCULAR)
+			goto slow_send;
+
+		dest_port = (ipc_port_t) kmsg->ikm_header.msgh_remote_port;
+		assert(IP_VALID(dest_port));
+
+		ip_lock(dest_port);
+		if (dest_port->ip_receiver == ipc_space_kernel) {
+			assert(ip_active(dest_port));
+			ip_unlock(dest_port);
+			goto kernel_send;
+		}
+
+		if (ip_active(dest_port) &&
+		    ((dest_port->ip_msgcount < dest_port->ip_qlimit) ||
+		     (MACH_MSGH_BITS_REMOTE(kmsg->ikm_header.msgh_bits) ==
+					MACH_MSG_TYPE_PORT_SEND_ONCE)))
+		{
+		    /*
+		     *	Try an optimized ipc_mqueue_copyin.
+		     *	It will work if this is a request message.
+		     */
+
+		    register ipc_port_t reply_port;
+
+		    reply_port = (ipc_port_t)
+					kmsg->ikm_header.msgh_local_port;
+		    if (IP_VALID(reply_port)) {
+			if (ip_lock_try(reply_port)) {
+			    if (ip_active(reply_port) &&
+				reply_port->ip_receiver == space &&
+				reply_port->ip_receiver_name == rcv_name &&
+				reply_port->ip_pset == IPS_NULL)
+			    {
+				/* Grab a reference to the reply port. */
+				rcv_object = (ipc_object_t) reply_port;
+				io_reference(rcv_object);
+				rcv_mqueue = &reply_port->ip_messages;
+				imq_lock(rcv_mqueue);
+				io_unlock(rcv_object);
+				goto fast_send_receive;
+			    }
+			    ip_unlock(reply_port);
+			}
+		    }
+		}
+
+		ip_unlock(dest_port);
+		goto slow_send;
+
+	    kernel_send:
+		/*
+		 *	Special case: send message to kernel services.
+		 *	The request message has been copied into the
+		 *	kmsg.  Nothing is locked.
+		 */
+
+	    {
+		register ipc_port_t	reply_port;
+
+		/*
+		 * Perform the kernel function.
+		 */
+
+		kmsg = ipc_kobject_server(kmsg);
+		if (kmsg == IKM_NULL) {
+			/*
+			 * No reply.  Take the
+			 * slow receive path.
+			 */
+			goto slow_get_rcv_port;
+		}
+
+		/*
+		 * Check that:
+		 *	the reply port is alive
+		 *	we hold the receive right
+		 *	the name has not changed.
+		 *	the port is not in a set
+		 * If any of these are not true,
+		 * we cannot directly receive the reply
+		 * message.
+		 */
+		reply_port = (ipc_port_t) kmsg->ikm_header.msgh_remote_port;
+		ip_lock(reply_port);
+
+		if ((!ip_active(reply_port)) ||
+		    (reply_port->ip_receiver != space) ||
+		    (reply_port->ip_receiver_name != rcv_name) ||
+		    (reply_port->ip_pset != IPS_NULL))
+		{
+			ip_unlock(reply_port);
+			ipc_mqueue_send_always(kmsg);
+			goto slow_get_rcv_port;
+		}
+
+		rcv_mqueue = &reply_port->ip_messages;
+		imq_lock(rcv_mqueue);
+		/* keep port locked, and don`t change ref count yet */
+
+		/*
+		 * If there are messages on the port
+		 * or other threads waiting for a message,
+		 * we cannot directly receive the reply.
+		 */
+		if ((ipc_thread_queue_first(&rcv_mqueue->imq_threads)
+			!= ITH_NULL) ||
+		    (ipc_kmsg_queue_first(&rcv_mqueue->imq_messages)
+			!= IKM_NULL))
+		{
+			imq_unlock(rcv_mqueue);
+			ip_unlock(reply_port);
+			ipc_mqueue_send_always(kmsg);
+			goto slow_get_rcv_port;
+		}
+
+		/*
+		 * We can directly receive this reply.
+		 * Since the kernel reply never blocks,
+		 * it holds no message_accepted request.
+		 * Since there were no messages queued
+		 * on the reply port, there should be
+		 * no threads blocked waiting to send.
+		 */
+
+		assert(kmsg->ikm_marequest == IMAR_NULL);
+		assert(ipc_thread_queue_first(&reply_port->ip_blocked)
+				== ITH_NULL);
+
+		dest_port = reply_port;
+		kmsg->ikm_header.msgh_seqno = dest_port->ip_seqno++;
+		imq_unlock(rcv_mqueue);
+
+		/*
+		 * inline ipc_object_release.
+		 * Port is still locked.
+		 * Reference count was not incremented.
+		 */
+		ip_check_unlock(reply_port);
+
+		/* copy out the kernel reply */
+		goto fast_copyout;
+	    }
+
+	    slow_send:
+		/*
+		 *	Nothing is locked.  We have acquired kmsg, but
+		 *	we still need to send it and receive a reply.
+		 */
+
+		mr = ipc_mqueue_send(kmsg, MACH_MSG_OPTION_NONE,
+				     MACH_MSG_TIMEOUT_NONE);
+		if (mr != MACH_MSG_SUCCESS) {
+			mr |= ipc_kmsg_copyout_pseudo(kmsg, space,
+						      current_map());
+
+			assert(kmsg->ikm_marequest == IMAR_NULL);
+			(void) ipc_kmsg_put(msg, kmsg,
+					    kmsg->ikm_header.msgh_size);
+			thread_syscall_return(mr);
+			/*NOTREACHED*/
+		}
+
+	    slow_get_rcv_port:
+		/*
+		 * We have sent the message.  Copy in the receive port.
+		 */
+		mr = ipc_mqueue_copyin(space, rcv_name,
+				       &temp_rcv_mqueue, &temp_rcv_object);
+		if (mr != MACH_MSG_SUCCESS) {
+			thread_syscall_return(mr);
+			/*NOTREACHED*/
+		}
+		rcv_mqueue = temp_rcv_mqueue;
+		rcv_object = temp_rcv_object;
+		/* hold ref for rcv_object; rcv_mqueue is locked */
+
+	/*
+	    slow_receive:
+	*/
+		/*
+		 *	Now we have sent the request and copied in rcv_name,
+		 *	so rcv_mqueue is locked and hold ref for rcv_object.
+		 *	Just receive a reply and try to get back to fast path.
+		 *
+		 *	ipc_mqueue_receive may not return, because if we block
+		 *	then our kernel stack may be discarded.  So we save
+		 *	state here for mach_msg_continue to pick up.
+		 */
+
+		self->ith_msg = msg;
+		self->ith_rcv_size = rcv_size;
+		self->ith_object = rcv_object;
+		self->ith_mqueue = rcv_mqueue;
+
+		mr = ipc_mqueue_receive(rcv_mqueue,
+					MACH_MSG_OPTION_NONE,
+					MACH_MSG_SIZE_MAX,
+					MACH_MSG_TIMEOUT_NONE,
+					FALSE, mach_msg_continue,
+		       			&temp_kmsg, &temp_seqno);
+		/* rcv_mqueue is unlocked */
+		ipc_object_release(rcv_object);
+		if (mr != MACH_MSG_SUCCESS) {
+			thread_syscall_return(mr);
+			/*NOTREACHED*/
+		}
+
+		(kmsg = temp_kmsg)->ikm_header.msgh_seqno = temp_seqno;
+		dest_port = (ipc_port_t) kmsg->ikm_header.msgh_remote_port;
+		goto fast_copyout;
+
+	    slow_copyout:
+		/*
+		 *	Nothing locked and no references held, except
+		 *	we have kmsg with msgh_seqno filled in.  Must
+		 *	still check against rcv_size and do
+		 *	ipc_kmsg_copyout/ipc_kmsg_put.
+		 */
+
+		reply_size = kmsg->ikm_header.msgh_size;
+		if (rcv_size < reply_size) {
+			ipc_kmsg_copyout_dest(kmsg, space);
+			(void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
+			thread_syscall_return(MACH_RCV_TOO_LARGE);
+			/*NOTREACHED*/
+		}
+
+		mr = ipc_kmsg_copyout(kmsg, space, current_map(),
+				      MACH_PORT_NULL);
+		if (mr != MACH_MSG_SUCCESS) {
+			if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
+				(void) ipc_kmsg_put(msg, kmsg,
+						kmsg->ikm_header.msgh_size);
+			} else {
+				ipc_kmsg_copyout_dest(kmsg, space);
+				(void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
+			}
+
+			thread_syscall_return(mr);
+			/*NOTREACHED*/
+		}
+
+		/* try to get back on optimized path */
+
+		goto fast_put;
+
+	    slow_put:
+		mr = ipc_kmsg_put(msg, kmsg, reply_size);
+		thread_syscall_return(mr);
+		/*NOTREACHED*/
+	    }
+	} else if (option == MACH_SEND_MSG) {
+		ipc_space_t space = current_space();
+		vm_map_t map = current_map();
+		ipc_kmsg_t kmsg;
+
+		mr = ipc_kmsg_get(msg, send_size, &kmsg);
+		if (mr != MACH_MSG_SUCCESS)
+			return mr;
+
+		mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
+		if (mr != MACH_MSG_SUCCESS) {
+			ikm_free(kmsg);
+			return mr;
+		}
+
+		mr = ipc_mqueue_send(kmsg, MACH_MSG_OPTION_NONE,
+				     MACH_MSG_TIMEOUT_NONE);
+		if (mr != MACH_MSG_SUCCESS) {
+			mr |= ipc_kmsg_copyout_pseudo(kmsg, space, map);
+
+			assert(kmsg->ikm_marequest == IMAR_NULL);
+			(void) ipc_kmsg_put(msg, kmsg,
+					    kmsg->ikm_header.msgh_size);
+		}
+
+		return mr;
+	} else if (option == MACH_RCV_MSG) {
+		ipc_thread_t self = current_thread();
+		ipc_space_t space = current_space();
+		vm_map_t map = current_map();
+		ipc_object_t object;
+		ipc_mqueue_t mqueue;
+		ipc_kmsg_t kmsg;
+		mach_port_seqno_t seqno;
+
+		mr = ipc_mqueue_copyin(space, rcv_name, &mqueue, &object);
+		if (mr != MACH_MSG_SUCCESS)
+			return mr;
+		/* hold ref for object; mqueue is locked */
+
+		/*
+		 *	ipc_mqueue_receive may not return, because if we block
+		 *	then our kernel stack may be discarded.  So we save
+		 *	state here for mach_msg_continue to pick up.
+		 */
+
+		self->ith_msg = msg;
+		self->ith_rcv_size = rcv_size;
+		self->ith_object = object;
+		self->ith_mqueue = mqueue;
+
+		mr = ipc_mqueue_receive(mqueue,
+					MACH_MSG_OPTION_NONE,
+					MACH_MSG_SIZE_MAX,
+					MACH_MSG_TIMEOUT_NONE,
+					FALSE, mach_msg_continue,
+					&kmsg, &seqno);
+		/* mqueue is unlocked */
+		ipc_object_release(object);
+		if (mr != MACH_MSG_SUCCESS)
+			return mr;
+
+		kmsg->ikm_header.msgh_seqno = seqno;
+		if (rcv_size < kmsg->ikm_header.msgh_size) {
+			ipc_kmsg_copyout_dest(kmsg, space);
+			(void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
+			return MACH_RCV_TOO_LARGE;
+		}
+
+		mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
+		if (mr != MACH_MSG_SUCCESS) {
+			if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
+				(void) ipc_kmsg_put(msg, kmsg,
+						kmsg->ikm_header.msgh_size);
+			} else {
+				ipc_kmsg_copyout_dest(kmsg, space);
+				(void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
+			}
+
+			return mr;
+		}
+
+		return ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
+	} else if (option == MACH_MSG_OPTION_NONE) {
+		/*
+		 *	We can measure the "null mach_msg_trap"
+		 *	(syscall entry and thread_syscall_return exit)
+		 *	with this path.
+		 */
+
+		thread_syscall_return(MACH_MSG_SUCCESS);
+		/*NOTREACHED*/
+	}
+#endif	/* CONTINUATIONS */
+
+	if (option & MACH_SEND_MSG) {
+		mr = mach_msg_send(msg, option, send_size,
+				   time_out, notify);
+		if (mr != MACH_MSG_SUCCESS)
+			return mr;
+	}
+
+	if (option & MACH_RCV_MSG) {
+		mr = mach_msg_receive(msg, option, rcv_size, rcv_name,
+				      time_out, notify);
+		if (mr != MACH_MSG_SUCCESS)
+			return mr;
+	}
+
+	return MACH_MSG_SUCCESS;
+}
+
+#ifdef CONTINUATIONS
+/*
+ *	Routine:	mach_msg_continue
+ *	Purpose:
+ *		Continue after blocking for a message.
+ *	Conditions:
+ *		Nothing locked.  We are running on a new kernel stack,
+ *		with the receive state saved in the thread.  From here
+ *		control goes back to user space.
+ */
+
+void
+mach_msg_continue()
+{
+	ipc_thread_t thread = current_thread();
+	task_t task = thread->task;
+	ipc_space_t space = task->itk_space;
+	vm_map_t map = task->map;
+	mach_msg_header_t *msg = thread->ith_msg;
+	mach_msg_size_t rcv_size = thread->ith_rcv_size;
+	ipc_object_t object = thread->ith_object;
+	ipc_mqueue_t mqueue = thread->ith_mqueue;
+	ipc_kmsg_t kmsg;
+	mach_port_seqno_t seqno;
+	mach_msg_return_t mr;
+
+	mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
+				MACH_MSG_SIZE_MAX, MACH_MSG_TIMEOUT_NONE,
+				TRUE, mach_msg_continue, &kmsg, &seqno);
+	/* mqueue is unlocked */
+	ipc_object_release(object);
+	if (mr != MACH_MSG_SUCCESS) {
+		thread_syscall_return(mr);
+		/*NOTREACHED*/
+	}
+
+	kmsg->ikm_header.msgh_seqno = seqno;
+	if (kmsg->ikm_header.msgh_size > rcv_size) {
+		ipc_kmsg_copyout_dest(kmsg, space);
+		(void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
+		thread_syscall_return(MACH_RCV_TOO_LARGE);
+		/*NOTREACHED*/
+	}
+
+	mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
+	if (mr != MACH_MSG_SUCCESS) {
+		if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
+			(void) ipc_kmsg_put(msg, kmsg,
+					kmsg->ikm_header.msgh_size);
+		} else {
+			ipc_kmsg_copyout_dest(kmsg, space);
+			(void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
+		}
+
+		thread_syscall_return(mr);
+		/*NOTREACHED*/
+	}
+
+	mr = ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
+	thread_syscall_return(mr);
+	/*NOTREACHED*/
+}
+
+/*
+ *	Routine:	mach_msg_interrupt
+ *	Purpose:
+ *		Attempts to force a thread waiting at mach_msg_continue or
+ *		mach_msg_receive_continue into a clean point.  Returns TRUE
+ *		if this was possible.
+ *	Conditions:
+ *		Nothing locked.  The thread must NOT be runnable.
+ */
+
+boolean_t
+mach_msg_interrupt(thread)
+	thread_t thread;
+{
+	ipc_mqueue_t mqueue;
+
+	assert((thread->swap_func == (void (*)()) mach_msg_continue) ||
+	       (thread->swap_func == (void (*)()) mach_msg_receive_continue));
+
+	mqueue = thread->ith_mqueue;
+	imq_lock(mqueue);
+	if (thread->ith_state != MACH_RCV_IN_PROGRESS) {
+		/*
+		 *	The thread is no longer waiting for a message.
+		 *	It may have a message sitting in ith_kmsg.
+		 *	We can't clean this up.
+		 */
+
+		imq_unlock(mqueue);
+		return FALSE;
+	}
+	ipc_thread_rmqueue(&mqueue->imq_threads, thread);
+	imq_unlock(mqueue);
+
+	ipc_object_release(thread->ith_object);
+
+	thread_set_syscall_return(thread, MACH_RCV_INTERRUPTED);
+	thread->swap_func = thread_exception_return;
+	return TRUE;
+}
+#endif /* CONTINUATIONS */
+
+#if	MACH_IPC_COMPAT
+
+/*
+ *	Routine:	msg_return_translate
+ *	Purpose:
+ *		Translate from new error code to old error code.
+ */
+
+msg_return_t
+msg_return_translate(mr)
+	mach_msg_return_t mr;
+{
+	switch (mr &~ MACH_MSG_MASK) {
+	    case MACH_MSG_SUCCESS:
+		return 0;	/* SEND_SUCCESS/RCV_SUCCESS/RPC_SUCCESS */
+
+	    case MACH_SEND_NO_BUFFER:
+	    case MACH_SEND_NO_NOTIFY:
+		printf("msg_return_translate: %x -> interrupted\n", mr);
+		return SEND_INTERRUPTED;
+
+	    case MACH_SEND_MSG_TOO_SMALL:
+		return SEND_MSG_TOO_SMALL;
+	    case MACH_SEND_INVALID_DATA:
+	    case MACH_SEND_INVALID_MEMORY:
+		return SEND_INVALID_MEMORY;
+	    case MACH_SEND_TIMED_OUT:
+		return SEND_TIMED_OUT;
+	    case MACH_SEND_INTERRUPTED:
+		return SEND_INTERRUPTED;
+	    case MACH_SEND_INVALID_DEST:
+	    case MACH_SEND_INVALID_REPLY:
+	    case MACH_SEND_INVALID_RIGHT:
+	    case MACH_SEND_INVALID_TYPE:
+		return SEND_INVALID_PORT;
+	    case MACH_SEND_WILL_NOTIFY:
+		return SEND_WILL_NOTIFY;
+	    case MACH_SEND_NOTIFY_IN_PROGRESS:
+		return SEND_NOTIFY_IN_PROGRESS;
+
+	    case MACH_RCV_INVALID_NAME:
+	    case MACH_RCV_IN_SET:
+	    case MACH_RCV_PORT_DIED:
+		return RCV_INVALID_PORT;
+	    case MACH_RCV_TOO_LARGE:
+		return RCV_TOO_LARGE;
+	    case MACH_RCV_TIMED_OUT:
+		return RCV_TIMED_OUT;
+	    case MACH_RCV_INTERRUPTED:
+		return RCV_INTERRUPTED;
+	    case MACH_RCV_PORT_CHANGED:
+		return RCV_PORT_CHANGE;
+	    case MACH_RCV_INVALID_DATA:
+		return RCV_INVALID_MEMORY;
+
+	    case MACH_SEND_IN_PROGRESS:
+	    case MACH_SEND_INVALID_NOTIFY:
+	    case MACH_SEND_INVALID_HEADER:
+	    case MACH_RCV_IN_PROGRESS:
+	    case MACH_RCV_INVALID_NOTIFY:
+	    case MACH_RCV_HEADER_ERROR:
+	    case MACH_RCV_BODY_ERROR:
+	    default:
+#if MACH_ASSERT
+		assert(!"msg_return_translate");
+#else
+		panic("msg_return_translate");
+#endif
+	}
+}
+
+/*
+ *	Routine:	msg_send_trap [mach trap]
+ *	Purpose:
+ *		Send a message.
+ *	Conditions:
+ *		Nothing locked.
+ *	Returns:
+ */
+
+msg_return_t
+msg_send_trap(msg, option, send_size, time_out)
+	msg_header_t *msg;
+	msg_option_t option;
+	msg_size_t send_size;
+	msg_timeout_t time_out;
+{
+	ipc_space_t space = current_space();
+	vm_map_t map = current_map();
+	ipc_kmsg_t kmsg;
+	mach_msg_return_t mr;
+
+	send_size = (send_size + 3) & ~3; /* round up */
+
+	if (send_size > MSG_SIZE_MAX)
+		return SEND_MSG_TOO_LARGE;
+
+	mr = ipc_kmsg_get((mach_msg_header_t *) msg,
+			  (mach_msg_size_t) send_size,
+			  &kmsg);
+	if (mr != MACH_MSG_SUCCESS)
+		return msg_return_translate(mr);
+
+	mr = ipc_kmsg_copyin_compat(kmsg, space, map);
+	if (mr != MACH_MSG_SUCCESS) {
+		ikm_free(kmsg);
+		return msg_return_translate(mr);
+	}
+
+	if (option & SEND_NOTIFY) {
+		mr = ipc_mqueue_send(kmsg, MACH_SEND_TIMEOUT,
+				     ((option & SEND_TIMEOUT) ?
+				      (mach_msg_timeout_t) time_out :
+				      MACH_MSG_TIMEOUT_NONE));
+		if (mr == MACH_SEND_TIMED_OUT) {
+			ipc_port_t dest = (ipc_port_t)
+				kmsg->ikm_header.msgh_remote_port;
+
+			mr = ipc_marequest_create(space, dest, MACH_PORT_NULL,
+						  &kmsg->ikm_marequest);
+			if (mr == MACH_MSG_SUCCESS) {
+				ipc_mqueue_send_always(kmsg);
+				return SEND_WILL_NOTIFY;
+			}
+		}
+	} else
+		mr = ipc_mqueue_send(kmsg,
+				     ((option & SEND_TIMEOUT) ?
+				      MACH_SEND_TIMEOUT :
+				      MACH_MSG_OPTION_NONE),
+				     (mach_msg_timeout_t) time_out);
+
+	if (mr != MACH_MSG_SUCCESS)
+		ipc_kmsg_destroy(kmsg);
+
+	return msg_return_translate(mr);
+}
+
+/*
+ *	Routine:	msg_receive_trap [mach trap]
+ *	Purpose:
+ *		Receive a message.
+ *	Conditions:
+ *		Nothing locked.
+ *	Returns:
+ */
+
+msg_return_t
+msg_receive_trap(msg, option, rcv_size, rcv_name, time_out)
+	msg_header_t *msg;
+	msg_option_t option;
+	msg_size_t rcv_size;
+	port_name_t rcv_name;
+	msg_timeout_t time_out;
+{
+	ipc_thread_t self;
+	ipc_space_t space = current_space();
+	vm_map_t map = current_map();
+	ipc_object_t object;
+	ipc_mqueue_t mqueue;
+	ipc_kmsg_t kmsg;
+	mach_port_seqno_t seqno;
+	mach_msg_return_t mr;
+
+	mr = ipc_mqueue_copyin(space, (mach_port_t) rcv_name,
+			       &mqueue, &object);
+	if (mr != MACH_MSG_SUCCESS)
+		return msg_return_translate(mr);
+	/* hold ref for object; mqueue is locked */
+
+#ifdef CONTINUATIONS
+	/*
+	 *	ipc_mqueue_receive may not return, because if we block
+	 *	then our kernel stack may be discarded.  So we save
+	 *	state here for msg_receive_continue to pick up.
+	 */
+
+	self = current_thread();
+	self->ith_msg = (mach_msg_header_t *) msg;
+	self->ith_option = (mach_msg_option_t) option;
+	self->ith_rcv_size = (mach_msg_size_t) rcv_size;
+	self->ith_timeout = (mach_msg_timeout_t) time_out;
+	self->ith_object = object;
+	self->ith_mqueue = mqueue;
+#endif /* CONTINUATIONS */
+
+	mr = ipc_mqueue_receive(mqueue,
+				(option & RCV_TIMEOUT) ?
+				MACH_RCV_TIMEOUT : MACH_MSG_OPTION_NONE,
+				(mach_msg_size_t) rcv_size,
+				(mach_msg_timeout_t) time_out,
+				FALSE, msg_receive_continue,
+				&kmsg, &seqno);
+	/* mqueue is unlocked */
+	ipc_object_release(object);
+	if (mr != MACH_MSG_SUCCESS) {
+		if (mr == MACH_RCV_TOO_LARGE) {
+			msg_size_t real_size =
+				(msg_size_t) (mach_msg_size_t) kmsg;
+
+			assert(real_size > rcv_size);
+
+			(void) copyout((vm_offset_t) &real_size,
+				       (vm_offset_t) &msg->msg_size,
+				       sizeof(msg_size_t));
+		}
+
+		return msg_return_translate(mr);
+	}
+
+	assert(kmsg->ikm_header.msgh_size <= (mach_msg_size_t) rcv_size);
+
+	mr = ipc_kmsg_copyout_compat(kmsg, space, map);
+	assert(mr == MACH_MSG_SUCCESS);
+
+	mr = ipc_kmsg_put((mach_msg_header_t *) msg, kmsg,
+			  kmsg->ikm_header.msgh_size);
+	return msg_return_translate(mr);
+}
+
+/*
+ *	Routine:	msg_rpc_trap [mach trap]
+ *	Purpose:
+ *		Send and receive a message.
+ *	Conditions:
+ *		Nothing locked.
+ *	Returns:
+ */
+
+msg_return_t
+msg_rpc_trap(msg, option, send_size, rcv_size, send_timeout, rcv_timeout)
+	msg_header_t *msg;
+	msg_option_t option;
+	msg_size_t send_size;
+	msg_size_t rcv_size;
+	msg_timeout_t send_timeout;
+	msg_timeout_t rcv_timeout;
+{
+	ipc_thread_t self;
+	ipc_space_t space = current_space();
+	vm_map_t map = current_map();
+	ipc_port_t reply;
+	ipc_pset_t pset;
+	ipc_mqueue_t mqueue;
+	ipc_kmsg_t kmsg;
+	mach_port_seqno_t seqno;
+	mach_msg_return_t mr;
+
+	/*
+	 *	Instead of using msg_send_trap and msg_receive_trap,
+	 *	we implement msg_rpc_trap directly.  The difference
+	 *	is how the reply port is handled.  Instead of using
+	 *	ipc_mqueue_copyin, we save a reference for the reply
+	 *	port carried in the sent message.  For example,
+	 *	consider a rename kernel call which changes the name
+	 *	of the call's own reply port.  This is the behaviour
+	 *	of the Mach 2.5 msg_rpc_trap.
+	 */
+
+	send_size = (send_size + 3) & ~3; /* round up */
+
+	if (send_size > MSG_SIZE_MAX)
+		return SEND_MSG_TOO_LARGE;
+
+	mr = ipc_kmsg_get((mach_msg_header_t *) msg,
+			  (mach_msg_size_t) send_size,
+			  &kmsg);
+	if (mr != MACH_MSG_SUCCESS)
+		return msg_return_translate(mr);
+
+	mr = ipc_kmsg_copyin_compat(kmsg, space, map);
+	if (mr != MACH_MSG_SUCCESS) {
+		ikm_free(kmsg);
+		return msg_return_translate(mr);
+	}
+
+	reply = (ipc_port_t) kmsg->ikm_header.msgh_local_port;
+	if (IP_VALID(reply))
+		ipc_port_reference(reply);
+
+	if (option & SEND_NOTIFY) {
+		mr = ipc_mqueue_send(kmsg, MACH_SEND_TIMEOUT,
+				     ((option & SEND_TIMEOUT) ?
+				      (mach_msg_timeout_t) send_timeout :
+				      MACH_MSG_TIMEOUT_NONE));
+		if (mr == MACH_SEND_TIMED_OUT) {
+			ipc_port_t dest = (ipc_port_t)
+				kmsg->ikm_header.msgh_remote_port;
+
+			mr = ipc_marequest_create(space, dest, MACH_PORT_NULL,
+						  &kmsg->ikm_marequest);
+			if (mr == MACH_MSG_SUCCESS) {
+				ipc_mqueue_send_always(kmsg);
+				if (IP_VALID(reply))
+					ipc_port_release(reply);
+				return SEND_WILL_NOTIFY;
+			}
+		}
+	} else
+		mr = ipc_mqueue_send(kmsg,
+				     ((option & SEND_TIMEOUT) ?
+				      MACH_SEND_TIMEOUT :
+				      MACH_MSG_OPTION_NONE),
+				     (mach_msg_timeout_t) send_timeout);
+
+	if (mr != MACH_MSG_SUCCESS) {
+		ipc_kmsg_destroy(kmsg);
+		if (IP_VALID(reply))
+			ipc_port_release(reply);
+		return msg_return_translate(mr);
+	}
+
+	if (!IP_VALID(reply))
+		return RCV_INVALID_PORT;
+
+	ip_lock(reply);
+	if (reply->ip_receiver != space) {
+		ip_release(reply);
+		ip_check_unlock(reply);
+		return RCV_INVALID_PORT;
+	}
+
+	assert(ip_active(reply));
+	pset = reply->ip_pset;
+
+	if (pset != IPS_NULL) {
+		ips_lock(pset);
+		if (ips_active(pset)) {
+			ips_unlock(pset);
+			ip_release(reply);
+			ip_unlock(reply);
+			return RCV_INVALID_PORT;
+		}
+
+		ipc_pset_remove(pset, reply);
+		ips_check_unlock(pset);
+		assert(reply->ip_pset == IPS_NULL);
+	}
+
+	mqueue = &reply->ip_messages;
+	imq_lock(mqueue);
+	ip_unlock(reply);
+
+#ifdef CONTINUATIONS
+	/*
+	 *	ipc_mqueue_receive may not return, because if we block
+	 *	then our kernel stack may be discarded.  So we save
+	 *	state here for msg_receive_continue to pick up.
+	 */
+
+	self = current_thread();
+	self->ith_msg = (mach_msg_header_t *) msg;
+	self->ith_option = (mach_msg_option_t) option;
+	self->ith_rcv_size = (mach_msg_size_t) rcv_size;
+	self->ith_timeout = (mach_msg_timeout_t) rcv_timeout;
+	self->ith_object = (ipc_object_t) reply;
+	self->ith_mqueue = mqueue;
+#endif /* CONTINUATIONS */
+
+	mr = ipc_mqueue_receive(mqueue,
+				(option & RCV_TIMEOUT) ?
+				MACH_RCV_TIMEOUT : MACH_MSG_OPTION_NONE,
+				(mach_msg_size_t) rcv_size,
+				(mach_msg_timeout_t) rcv_timeout,
+				FALSE, msg_receive_continue,
+				&kmsg, &seqno);
+	/* mqueue is unlocked */
+	ipc_port_release(reply);
+	if (mr != MACH_MSG_SUCCESS) {
+		if (mr == MACH_RCV_TOO_LARGE) {
+			msg_size_t real_size =
+				(msg_size_t) (mach_msg_size_t) kmsg;
+
+			assert(real_size > rcv_size);
+
+			(void) copyout((vm_offset_t) &real_size,
+				       (vm_offset_t) &msg->msg_size,
+				       sizeof(msg_size_t));
+		}
+
+		return msg_return_translate(mr);
+	}
+
+	assert(kmsg->ikm_header.msgh_size <= (mach_msg_size_t) rcv_size);
+
+	mr = ipc_kmsg_copyout_compat(kmsg, space, map);
+	assert(mr == MACH_MSG_SUCCESS);
+
+	mr = ipc_kmsg_put((mach_msg_header_t *) msg,
+			  kmsg, kmsg->ikm_header.msgh_size);
+	return msg_return_translate(mr);
+}
+
+#ifdef CONTINUATIONS
+/*
+ *	Routine:	msg_receive_continue
+ *	Purpose:
+ *		Continue after blocking for a message.
+ *	Conditions:
+ *		Nothing locked.  We are running on a new kernel stack,
+ *		with the receive state saved in the thread.  From here
+ *		control goes back to user space.
+ */
+
+void
+msg_receive_continue()
+{
+	ipc_thread_t self = current_thread();
+	msg_header_t *msg = (msg_header_t *) self->ith_msg;
+	msg_option_t option = (msg_option_t) self->ith_option;
+	msg_size_t rcv_size = (msg_size_t) self->ith_rcv_size;
+	msg_timeout_t time_out = (msg_timeout_t) self->ith_timeout;
+	ipc_object_t object = self->ith_object;
+	ipc_mqueue_t mqueue = self->ith_mqueue;
+	ipc_kmsg_t kmsg;
+	mach_port_seqno_t seqno;
+	mach_msg_return_t mr;
+
+	mr = ipc_mqueue_receive(mqueue,
+				(option & RCV_TIMEOUT) ?
+				MACH_RCV_TIMEOUT : MACH_MSG_OPTION_NONE,
+				(mach_msg_size_t) rcv_size,
+				(mach_msg_timeout_t) time_out,
+				TRUE, msg_receive_continue,
+				&kmsg, &seqno);
+	/* mqueue is unlocked */
+	ipc_object_release(object);
+	if (mr != MACH_MSG_SUCCESS) {
+		if (mr == MACH_RCV_TOO_LARGE) {
+			msg_size_t real_size =
+				(msg_size_t) (mach_msg_size_t) kmsg;
+
+			assert(real_size > rcv_size);
+
+			(void) copyout((vm_offset_t) &real_size,
+				       (vm_offset_t) &msg->msg_size,
+				       sizeof(msg_size_t));
+		}
+
+		thread_syscall_return(msg_return_translate(mr));
+		/*NOTREACHED*/
+	}
+
+	assert(kmsg->ikm_header.msgh_size <= (mach_msg_size_t) rcv_size);
+
+	mr = ipc_kmsg_copyout_compat(kmsg, current_space(), current_map());
+	assert(mr == MACH_MSG_SUCCESS);
+
+	mr = ipc_kmsg_put((mach_msg_header_t *) msg, kmsg,
+			  kmsg->ikm_header.msgh_size);
+	thread_syscall_return(msg_return_translate(mr));
+	/*NOTREACHED*/
+}
+#endif /* CONTINUATIONS */
+
+#endif	/* MACH_IPC_COMPAT */
diff -Npur gnumach.old/kern/eventcount.c gnumach.new/kern/eventcount.c
--- gnumach.old/kern/eventcount.c	1997-02-25 18:28:22.000000000 -0300
+++ gnumach.new/kern/eventcount.c	2006-04-05 23:32:04.000000000 -0300
@@ -125,7 +125,6 @@ void evc_notify_abort(thread_t thread)
     splx(s);
 }
 
-#ifdef CONTINUATIONS
 /*
  * Just so that we return success, and give
  * up the stack while blocked
@@ -136,9 +135,6 @@ evc_continue(void)
 	thread_syscall_return(KERN_SUCCESS);
 	/* NOTREACHED */
 }
-#else /* not CONTINUATIONS */
-#define evc_continue 0
-#endif /* not CONTINUATIONS */
 
 /*
  * User-trappable
diff -Npur gnumach.old/kern/eventcount.c.~1.1.1.1.~ gnumach.new/kern/eventcount.c.~1.1.1.1.~
--- gnumach.old/kern/eventcount.c.~1.1.1.1.~	1969-12-31 21:00:00.000000000 -0300
+++ gnumach.new/kern/eventcount.c.~1.1.1.1.~	1997-02-25 18:28:22.000000000 -0300
@@ -0,0 +1,372 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
+ * Copyright (c) 1993,1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL).
+ * 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, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
+ * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
+ * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
+ * THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ *	File:	eventcount.c
+ *	Author:	Alessandro Forin
+ *	Date:	10/91
+ *
+ *	Eventcounters, for user-level drivers synchronization
+ *
+ */
+
+
+#include <cpus.h>
+
+#include <mach/machine.h>
+#include <kern/ast.h>
+#include "cpu_number.h"
+#include <kern/lock.h>
+#include <kern/processor.h>
+#include <kern/queue.h>
+#include <kern/sched.h>
+#include <kern/sched_prim.h>
+#include <kern/thread.h>
+
+#include <machine/machspl.h>	/* For def'n of splsched() */
+
+#include <kern/eventcount.h>
+
+
+#if  NCPUS <= 1
+void simpler_thread_setrun(
+	thread_t	th,
+	boolean_t	may_preempt); /* forward */
+#endif
+
+#define	MAX_EVCS	10		/* xxx for now */
+evc_t	all_eventcounters[MAX_EVCS];
+
+/*
+ * Initialization
+ */
+void
+evc_init(evc_t	ev)
+{
+	int i;
+
+	bzero((char*)ev, sizeof(*ev));
+
+	/* keep track of who is who */
+	for (i = 0; i < MAX_EVCS; i++)
+		if (all_eventcounters[i] == 0) break;
+	if (i == MAX_EVCS) {
+		printf("Too many eventcounters\n");
+		return;
+	}
+
+	all_eventcounters[i] = ev;
+	ev->ev_id = i;
+	ev->sanity = ev;
+	ev->waiting_thread = THREAD_NULL;
+	simple_lock_init(&ev->lock);
+}
+
+/*
+ * Finalization
+ */
+void
+evc_destroy(evc_t	ev)
+{
+	evc_signal(ev);
+	ev->sanity = 0;
+	if (all_eventcounters[ev->ev_id] == ev)
+		all_eventcounters[ev->ev_id] = 0;
+	ev->ev_id = -1;
+}
+
+/*
+ * Thread termination.
+ * HORRIBLE. This stuff needs to be fixed.
+ */
+void evc_notify_abort(thread_t thread)
+{
+    int i;
+    evc_t ev;
+    int s = splsched();
+    for (i = 0; i < MAX_EVCS; i++)  {
+	ev = all_eventcounters[i];
+	if (ev)  {
+	    simple_lock(&ev->lock);
+	    if (ev->waiting_thread == thread)  
+	      {
+		ev->waiting_thread = 0;
+		/* Removal of a waiting thread has to bump the count by one */
+		ev->count++;
+	      }
+	    simple_unlock(&ev->lock);
+	}
+    }
+    splx(s);
+}
+
+#ifdef CONTINUATIONS
+/*
+ * Just so that we return success, and give
+ * up the stack while blocked
+ */
+static void
+evc_continue(void)
+{
+	thread_syscall_return(KERN_SUCCESS);
+	/* NOTREACHED */
+}
+#else /* not CONTINUATIONS */
+#define evc_continue 0
+#endif /* not CONTINUATIONS */
+
+/*
+ * User-trappable
+ */
+kern_return_t evc_wait(natural_t ev_id)
+{
+	spl_t		s;
+	kern_return_t	ret;
+	evc_t		ev;
+
+	if ((ev_id >= MAX_EVCS) ||
+	    ((ev = all_eventcounters[ev_id]) == 0) ||
+	    (ev->ev_id != ev_id) || (ev->sanity != ev))
+		return KERN_INVALID_ARGUMENT;
+
+	s = splsched();
+	simple_lock(&ev->lock);
+		/*
+		 * The values assumed by the "count" field are
+		 * as follows:
+		 *	0	At initialization time, and with no
+		 *		waiting thread means no events pending;
+		 *		with waiting thread means the event
+		 *		was signalled and the thread not yet resumed
+		 *	-1	no events, there must be a waiting thread
+		 *	N>0	no waiting thread means N pending,
+		 *		with waiting thread N-1 pending.
+		 *	
+		 */
+		if (ev->count > 0) {
+			ev->count--;
+			ret = KERN_SUCCESS;
+		} else {
+			if (ev->waiting_thread == THREAD_NULL) {
+				ev->count--;
+				ev->waiting_thread = current_thread();
+				assert_wait((event_t) 0, TRUE);	/* ifnot race */
+				simple_unlock(&ev->lock);
+				thread_block(evc_continue);
+				return KERN_SUCCESS;
+			}
+			ret = KERN_NO_SPACE; /* XX */
+		}
+	simple_unlock(&ev->lock);
+	splx(s);
+	return ret;
+}
+
+/*
+ * User-trappable
+ */
+kern_return_t evc_wait_clear(natural_t ev_id)
+{
+	spl_t		s;
+	kern_return_t	ret;
+	evc_t		ev;
+
+	if ((ev_id >= MAX_EVCS) ||
+	    ((ev = all_eventcounters[ev_id]) == 0) ||
+	    (ev->ev_id != ev_id) || (ev->sanity != ev))
+		return KERN_INVALID_ARGUMENT;
+
+	s = splsched();
+	simple_lock(&ev->lock);
+
+		/*
+		 * The values assumed by the "count" field are
+		 * as follows:
+		 *	0	At initialization time, and with no
+		 *		waiting thread means no events pending;
+		 *		with waiting thread means the event
+		 *		was signalled and the thread not yet resumed
+		 *	-1	no events, there must be a waiting thread
+		 *	N>0	no waiting thread means N pending,
+		 *		with waiting thread N-1 pending.
+		 *	
+		 */
+	        /*
+		 *  Note that we always clear count before blocking.
+		 */
+		if (ev->waiting_thread == THREAD_NULL) {
+			ev->count = -1;
+			ev->waiting_thread = current_thread();
+			assert_wait((event_t) 0, TRUE);	/* ifnot race */
+			simple_unlock(&ev->lock);
+			thread_block(evc_continue);
+			/* NOTREACHED */
+		}
+
+	simple_unlock(&ev->lock);
+	splx(s);
+	ret = KERN_NO_SPACE; /* XX */
+}
+
+/*
+ * Called exclusively from interrupt context
+ */
+void
+evc_signal(evc_t ev)
+{
+    register volatile thread_t thread;
+    register int state;
+    spl_t    s;
+    if (ev->sanity != ev)
+      return;
+
+    s = splsched();
+    simple_lock(&ev->lock);
+    ev->count++;
+    if (thread = ev->waiting_thread, thread != THREAD_NULL)
+    {
+	ev->waiting_thread = 0;
+
+#if (NCPUS > 1)
+      retry:
+	while((thread->state & TH_RUN) || thread->lock.lock_data)
+		;
+#endif
+	thread_lock(thread);
+
+	/* make thread runnable on this processor */
+	/* taken from clear_wait */
+	switch ((state = thread->state) & TH_SCHED_STATE)
+	{
+	    case  TH_WAIT | TH_SUSP | TH_UNINT:
+	    case  TH_WAIT           | TH_UNINT:
+	    case  TH_WAIT:
+		/*
+		 *	Sleeping and not suspendable - put
+		 *	on run queue.
+		 */
+		thread->state = (state &~ TH_WAIT) | TH_RUN;
+		thread_unlock(thread);
+#if NCPUS > 1
+		thread_setrun(thread, TRUE);
+#else
+		simpler_thread_setrun(thread, TRUE);
+#endif
+		break;
+
+	    case TH_RUN | TH_WAIT:
+#if (NCPUS > 1)
+		/*
+		 * Legal on MP: between assert_wait()
+		 * and thread_block(), in evc_wait() above.
+		 *
+	 	 * Mmm. Maybe don't need now that the while(..) check is
+		 * done before the thread lock is grabbed.....
+		 */
+		thread_unlock(thread);
+		goto retry;
+#else
+		/*FALLTHROUGH*/
+#endif
+	    case          TH_WAIT | TH_SUSP:
+	    case TH_RUN | TH_WAIT | TH_SUSP:
+	    case TH_RUN | TH_WAIT           | TH_UNINT:
+	    case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
+
+		/*
+		 *	Either already running, or suspended.
+		 *      Just clear the wait.
+		 */
+		thread->state = state &~ TH_WAIT;
+		thread_unlock(thread);
+		break;
+
+	    default:
+		/*
+		 *	Not waiting.
+		 */
+		panic("evc_signal.3");
+		thread_unlock(thread);
+		break;
+	}
+    }
+
+    simple_unlock(&ev->lock);
+    splx(s);
+}
+
+#if	NCPUS <= 1
+/*
+ * The scheduler is too messy for my old little brain
+ */
+void
+simpler_thread_setrun(
+	thread_t	th,
+	boolean_t	may_preempt)
+{
+	register struct run_queue	*rq;
+	register			whichq;
+
+	/*
+	 *	XXX should replace queue with a boolean in this case.
+	 */
+	if (default_pset.idle_count > 0) {
+		processor_t	processor;
+
+		processor = (processor_t) queue_first(&default_pset.idle_queue);
+		queue_remove(&default_pset.idle_queue, processor,
+		processor_t, processor_queue);
+		default_pset.idle_count--;
+		processor->next_thread = th;
+		processor->state = PROCESSOR_DISPATCHING;
+		return;
+	}
+	rq = &(master_processor->runq);
+	ast_on(cpu_number(), AST_BLOCK);
+
+	whichq = (th)->sched_pri;
+	simple_lock(&(rq)->lock);	/* lock the run queue */
+	enqueue_head(&(rq)->runq[whichq], (queue_entry_t) (th));
+
+	if (whichq < (rq)->low || (rq)->count == 0)
+		 (rq)->low = whichq;	/* minimize */
+	(rq)->count++;
+#ifdef MIGRATING_THREADS
+	(th)->shuttle.runq = (rq);
+#else
+	(th)->runq = (rq);
+#endif
+	simple_unlock(&(rq)->lock);
+
+	/*
+	 *	Turn off first_quantum to allow context switch.
+	 */
+	current_processor()->first_quantum = FALSE;
+}
+#endif	/* NCPUS > 1 */
+
diff -Npur gnumach.old/kern/ipc_sched.c gnumach.new/kern/ipc_sched.c
--- gnumach.old/kern/ipc_sched.c	1997-02-25 18:28:23.000000000 -0300
+++ gnumach.new/kern/ipc_sched.c	2006-04-05 23:32:57.000000000 -0300
@@ -168,7 +168,6 @@ thread_will_wait_with_timeout(
 #define	check_bound_processor(thread)	TRUE
 #endif	/* NCPUS > 1 */
 
-#ifdef CONTINUATIONS
 /*
  *	Routine:	thread_handoff
  *	Purpose:
@@ -284,4 +283,3 @@ thread_handoff(
 	counter_always(c_thread_handoff_hits++);
 	return TRUE;
 }
-#endif /* CONTINUATIONS */
diff -Npur gnumach.old/kern/ipc_sched.c.~1.1.1.1.~ gnumach.new/kern/ipc_sched.c.~1.1.1.1.~
--- gnumach.old/kern/ipc_sched.c.~1.1.1.1.~	1969-12-31 21:00:00.000000000 -0300
+++ gnumach.new/kern/ipc_sched.c.~1.1.1.1.~	1997-02-25 18:28:23.000000000 -0300
@@ -0,0 +1,287 @@
+/* 
+ * Mach Operating System
+ * Copyright (c) 1993, 1992,1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <cpus.h>
+#include <mach_host.h>
+
+#include <mach/message.h>
+#include <kern/counters.h>
+#include "cpu_number.h"
+#include <kern/lock.h>
+#include <kern/thread.h>
+#include <kern/sched_prim.h>
+#include <kern/processor.h>
+#include <kern/time_out.h>
+#include <kern/thread_swap.h>
+#include <kern/ipc_sched.h>
+#include <machine/machspl.h>	/* for splsched/splx */
+#include <machine/pmap.h>
+
+
+
+/*
+ *	These functions really belong in kern/sched_prim.c.
+ */
+
+/*
+ *	Routine:	thread_go
+ *	Purpose:
+ *		Start a thread running.
+ *	Conditions:
+ *		IPC locks may be held.
+ */
+
+void
+thread_go(
+	thread_t thread)
+{
+	int	state;
+	spl_t	s;
+
+	s = splsched();
+	thread_lock(thread);
+
+	reset_timeout_check(&thread->timer);
+
+	state = thread->state;
+	switch (state & TH_SCHED_STATE) {
+
+	    case TH_WAIT | TH_SUSP | TH_UNINT:
+	    case TH_WAIT	   | TH_UNINT:
+	    case TH_WAIT:
+		/*
+		 *	Sleeping and not suspendable - put
+		 *	on run queue.
+		 */
+		thread->state = (state &~ TH_WAIT) | TH_RUN;
+		thread->wait_result = THREAD_AWAKENED;
+		thread_setrun(thread, TRUE);
+		break;
+
+	    case	  TH_WAIT | TH_SUSP:
+	    case TH_RUN | TH_WAIT:
+	    case TH_RUN | TH_WAIT | TH_SUSP:
+	    case TH_RUN | TH_WAIT	    | TH_UNINT:
+	    case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
+		/*
+		 *	Either already running, or suspended.
+		 */
+		thread->state = state & ~TH_WAIT;
+		thread->wait_result = THREAD_AWAKENED;
+		break;
+
+	    default:
+		/*
+		 *	Not waiting.
+		 */
+		break;
+	}
+
+	thread_unlock(thread);
+	splx(s);
+}
+
+/*
+ *	Routine:	thread_will_wait
+ *	Purpose:
+ *		Assert that the thread intends to block.
+ */
+
+void
+thread_will_wait(
+	thread_t thread)
+{
+	spl_t	s;
+
+	s = splsched();
+	thread_lock(thread);
+
+	assert(thread->wait_result = -1);	/* for later assertions */
+	thread->state |= TH_WAIT;
+
+	thread_unlock(thread);
+	splx(s);
+}
+
+/*
+ *	Routine:	thread_will_wait_with_timeout
+ *	Purpose:
+ *		Assert that the thread intends to block,
+ *		with a timeout.
+ */
+
+void
+thread_will_wait_with_timeout(
+	thread_t thread,
+	mach_msg_timeout_t msecs)
+{
+	natural_t ticks = convert_ipc_timeout_to_ticks(msecs);
+	spl_t	s;
+
+	s = splsched();
+	thread_lock(thread);
+
+	assert(thread->wait_result = -1);	/* for later assertions */
+	thread->state |= TH_WAIT;
+
+	set_timeout(&thread->timer, ticks);
+
+	thread_unlock(thread);
+	splx(s);
+}
+
+#if	MACH_HOST
+#define check_processor_set(thread)	\
+	    (current_processor()->processor_set == (thread)->processor_set)
+#else	/* MACH_HOST */
+#define	check_processor_set(thread)	TRUE
+#endif	/* MACH_HOST */
+
+#if	NCPUS > 1
+#define	check_bound_processor(thread) \
+	    ((thread)->bound_processor == PROCESSOR_NULL || \
+	     (thread)->bound_processor == current_processor())
+#else	/* NCPUS > 1 */
+#define	check_bound_processor(thread)	TRUE
+#endif	/* NCPUS > 1 */
+
+#ifdef CONTINUATIONS
+/*
+ *	Routine:	thread_handoff
+ *	Purpose:
+ *		Switch to a new thread (new), leaving the current
+ *		thread (old) blocked.  If successful, moves the
+ *		kernel stack from old to new and returns as the
+ *		new thread.  An explicit continuation for the old thread
+ *		must be supplied.
+ *
+ *		NOTE:  Although we wakeup new, we don't set new->wait_result.
+ *	Returns:
+ *		TRUE if the handoff happened.
+ */
+
+boolean_t
+thread_handoff(
+	register thread_t old,
+	register continuation_t continuation,
+	register thread_t new)
+{
+	spl_t	s;
+
+	assert(current_thread() == old);
+
+	/*
+	 *	XXX Dubious things here:
+	 *	I don't check the idle_count on the processor set.
+	 *	No scheduling priority or policy checks.
+	 *	I assume the new thread is interruptible.
+	 */
+
+	s = splsched();
+	thread_lock(new);
+
+	/*
+	 *	The first thing we must do is check the state
+	 *	of the threads, to ensure we can handoff.
+	 *	This check uses current_processor()->processor_set,
+	 *	which we can read without locking.
+	 */
+
+	if ((old->stack_privilege == current_stack()) ||
+	    (new->state != (TH_WAIT|TH_SWAPPED)) ||
+	     !check_processor_set(new) ||
+	     !check_bound_processor(new)) {
+		thread_unlock(new);
+		(void) splx(s);
+
+		counter_always(c_thread_handoff_misses++);
+		return FALSE;
+	}
+
+	reset_timeout_check(&new->timer);
+
+	new->state = TH_RUN;
+	thread_unlock(new);
+
+#if	NCPUS > 1
+	new->last_processor = current_processor();
+#endif	/* NCPUS > 1 */
+
+	ast_context(new, cpu_number());
+	timer_switch(&new->system_timer);
+
+	/*
+	 *	stack_handoff is machine-dependent.  It does the
+	 *	machine-dependent components of a context-switch, like
+	 *	changing address spaces.  It updates active_threads.
+	 */
+
+	stack_handoff(old, new);
+
+	/*
+	 *	Now we must dispose of the old thread.
+	 *	This is like thread_continue, except
+	 *	that the old thread isn't waiting yet.
+	 */
+
+	thread_lock(old);
+	old->swap_func = continuation;
+	assert(old->wait_result = -1);		/* for later assertions */
+
+	if (old->state == TH_RUN) {
+		/*
+		 *	This is our fast path.
+		 */
+
+		old->state = TH_WAIT|TH_SWAPPED;
+	}
+	else if (old->state == (TH_RUN|TH_SUSP)) {
+		/*
+		 *	Somebody is trying to suspend the thread.
+		 */
+
+		old->state = TH_WAIT|TH_SUSP|TH_SWAPPED;
+		if (old->wake_active) {
+			/*
+			 *	Someone wants to know when the thread
+			 *	really stops.
+			 */
+			old->wake_active = FALSE;
+			thread_unlock(old);
+			thread_wakeup((event_t)&old->wake_active);
+			goto after_old_thread;
+		}
+	} else
+		panic("thread_handoff");
+
+	thread_unlock(old);
+    after_old_thread:
+	(void) splx(s);
+
+	counter_always(c_thread_handoff_hits++);
+	return TRUE;
+}
+#endif /* CONTINUATIONS */
diff -Npur gnumach.old/kern/syscall_subr.c gnumach.new/kern/syscall_subr.c
--- gnumach.old/kern/syscall_subr.c	2001-04-05 03:39:20.000000000 -0300
+++ gnumach.new/kern/syscall_subr.c	2006-04-05 23:34:35.000000000 -0300
@@ -68,7 +68,6 @@
 extern void thread_depress_priority();
 extern kern_return_t thread_depress_abort();
 
-#ifdef CONTINUATIONS
 void swtch_continue()
 {
 	register processor_t	myprocessor;
@@ -78,9 +77,6 @@ void swtch_continue()
 			      myprocessor->processor_set->runq.count > 0);
 	/*NOTREACHED*/
 }
-#else	/* not CONTINUATIONS */
-#define swtch_continue 0
-#endif	/* not CONTINUATIONS */
 
 boolean_t swtch()
 {
@@ -100,7 +96,6 @@ boolean_t swtch()
 	       myprocessor->processor_set->runq.count > 0);
 }
 
-#ifdef CONTINUATIONS
 void swtch_pri_continue()
 {
 	register thread_t	thread = current_thread();
@@ -113,9 +108,6 @@ void swtch_pri_continue()
 			      myprocessor->processor_set->runq.count > 0);
 	/*NOTREACHED*/
 }
-#else	/* not CONTINUATIONS */
-#define swtch_pri_continue 0
-#endif	/* not CONTINUATIONS */
 
 boolean_t  swtch_pri(pri)
 	int pri;
@@ -152,7 +144,6 @@ boolean_t  swtch_pri(pri)
 
 extern int hz;
 
-#ifdef CONTINUATIONS
 void thread_switch_continue()
 {
 	register thread_t	cur_thread = current_thread();
@@ -165,9 +156,6 @@ void thread_switch_continue()
 	thread_syscall_return(KERN_SUCCESS);
 	/*NOTREACHED*/
 }
-#else	/* not CONTINUATIONS */
-#define thread_switch_continue 0
-#endif	/* not CONTINUATIONS */
 
 /*
  *	thread_switch:
diff -Npur gnumach.old/kern/syscall_subr.c.~1.2.~ gnumach.new/kern/syscall_subr.c.~1.2.~
--- gnumach.old/kern/syscall_subr.c.~1.2.~	1969-12-31 21:00:00.000000000 -0300
+++ gnumach.new/kern/syscall_subr.c.~1.2.~	2001-04-05 03:39:20.000000000 -0300
@@ -0,0 +1,399 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
+ * Copyright (c) 1993,1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL).
+ * 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, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
+ * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
+ * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
+ * THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <mach_fixpri.h>
+#include <cpus.h>
+
+#include <mach/boolean.h>
+#include <mach/thread_switch.h>
+#include <ipc/ipc_port.h>
+#include <ipc/ipc_space.h>
+#include <kern/counters.h>
+#include <kern/ipc_kobject.h>
+#include <kern/processor.h>
+#include <kern/sched.h>
+#include <kern/sched_prim.h>
+#include <kern/ipc_sched.h>
+#include <kern/task.h>
+#include <kern/thread.h>
+#include <kern/time_out.h>
+#include <machine/machspl.h>	/* for splsched */
+
+#if	MACH_FIXPRI
+#include <mach/policy.h>
+#endif	/* MACH_FIXPRI */
+
+
+
+/*
+ *	swtch and swtch_pri both attempt to context switch (logic in
+ *	thread_block no-ops the context switch if nothing would happen).
+ *	A boolean is returned that indicates whether there is anything
+ *	else runnable.
+ *
+ *	This boolean can be used by a thread waiting on a
+ *	lock or condition:  If FALSE is returned, the thread is justified
+ *	in becoming a resource hog by continuing to spin because there's
+ *	nothing else useful that the processor could do.  If TRUE is
+ *	returned, the thread should make one more check on the
+ *	lock and then be a good citizen and really suspend.
+ */
+
+extern void thread_depress_priority();
+extern kern_return_t thread_depress_abort();
+
+#ifdef CONTINUATIONS
+void swtch_continue()
+{
+	register processor_t	myprocessor;
+
+	myprocessor = current_processor();
+	thread_syscall_return(myprocessor->runq.count > 0 ||
+			      myprocessor->processor_set->runq.count > 0);
+	/*NOTREACHED*/
+}
+#else	/* not CONTINUATIONS */
+#define swtch_continue 0
+#endif	/* not CONTINUATIONS */
+
+boolean_t swtch()
+{
+	register processor_t	myprocessor;
+
+#if	NCPUS > 1
+	myprocessor = current_processor();
+	if (myprocessor->runq.count == 0 &&
+	    myprocessor->processor_set->runq.count == 0)
+		return(FALSE);
+#endif	/* NCPUS > 1 */
+
+	counter(c_swtch_block++);
+	thread_block(swtch_continue);
+	myprocessor = current_processor();
+	return(myprocessor->runq.count > 0 ||
+	       myprocessor->processor_set->runq.count > 0);
+}
+
+#ifdef CONTINUATIONS
+void swtch_pri_continue()
+{
+	register thread_t	thread = current_thread();
+	register processor_t	myprocessor;
+
+	if (thread->depress_priority >= 0)
+		(void) thread_depress_abort(thread);
+	myprocessor = current_processor();
+	thread_syscall_return(myprocessor->runq.count > 0 ||
+			      myprocessor->processor_set->runq.count > 0);
+	/*NOTREACHED*/
+}
+#else	/* not CONTINUATIONS */
+#define swtch_pri_continue 0
+#endif	/* not CONTINUATIONS */
+
+boolean_t  swtch_pri(pri)
+	int pri;
+{
+	register thread_t	thread = current_thread();
+	register processor_t	myprocessor;
+
+#ifdef	lint
+	pri++;
+#endif	/* lint */
+
+#if	NCPUS > 1
+	myprocessor = current_processor();
+	if (myprocessor->runq.count == 0 &&
+	    myprocessor->processor_set->runq.count == 0)
+		return(FALSE);
+#endif	/* NCPUS > 1 */
+
+	/*
+	 *	XXX need to think about depression duration.
+	 *	XXX currently using min quantum.
+	 */
+	thread_depress_priority(thread, min_quantum);
+
+	counter(c_swtch_pri_block++);
+	thread_block(swtch_pri_continue);
+
+	if (thread->depress_priority >= 0)
+		(void) thread_depress_abort(thread);
+	myprocessor = current_processor();
+	return(myprocessor->runq.count > 0 ||
+	       myprocessor->processor_set->runq.count > 0);
+}
+
+extern int hz;
+
+#ifdef CONTINUATIONS
+void thread_switch_continue()
+{
+	register thread_t	cur_thread = current_thread();
+
+	/*
+	 *  Restore depressed priority
+	 */
+	if (cur_thread->depress_priority >= 0)
+		(void) thread_depress_abort(cur_thread);
+	thread_syscall_return(KERN_SUCCESS);
+	/*NOTREACHED*/
+}
+#else	/* not CONTINUATIONS */
+#define thread_switch_continue 0
+#endif	/* not CONTINUATIONS */
+
+/*
+ *	thread_switch:
+ *
+ *	Context switch.  User may supply thread hint.
+ *
+ *	Fixed priority threads that call this get what they asked for
+ *	even if that violates priority order.
+ */
+kern_return_t thread_switch(thread_name, option, option_time)
+mach_port_t thread_name;
+int option;
+mach_msg_timeout_t option_time;
+{
+    register thread_t		cur_thread = current_thread();
+    register processor_t	myprocessor;
+    ipc_port_t			port;
+
+    /*
+     *	Process option.
+     */
+    switch (option) {
+	case SWITCH_OPTION_NONE:
+	    /*
+	     *	Nothing to do.
+	     */
+	    break;
+
+	case SWITCH_OPTION_DEPRESS:
+	    /*
+	     *	Depress priority for given time.
+	     */
+	    thread_depress_priority(cur_thread, option_time);
+	    break;
+
+	case SWITCH_OPTION_WAIT:
+	    thread_will_wait_with_timeout(cur_thread, option_time);
+	    break;
+
+	default:
+	    return(KERN_INVALID_ARGUMENT);
+    }
+
+#ifndef MIGRATING_THREADS /* XXX thread_run defunct */
+    /*
+     *	Check and act on thread hint if appropriate.
+     */
+    if ((thread_name != 0) &&
+	(ipc_port_translate_send(cur_thread->task->itk_space,
+				 thread_name, &port) == KERN_SUCCESS)) {
+	    /* port is locked, but it might not be active */
+
+	    /*
+	     *	Get corresponding thread.
+	     */
+	    if (ip_active(port) && (ip_kotype(port) == IKOT_THREAD)) {
+		register thread_t thread;
+		register spl_t s;
+
+		thread = (thread_t) port->ip_kobject;
+		/*
+		 *	Check if the thread is in the right pset. Then
+		 *	pull it off its run queue.  If it
+		 *	doesn't come, then it's not eligible.
+		 */
+		s = splsched();
+		thread_lock(thread);
+		if ((thread->processor_set == cur_thread->processor_set)
+		    && (rem_runq(thread) != RUN_QUEUE_NULL)) {
+			/*
+			 *	Hah, got it!!
+			 */
+			thread_unlock(thread);
+			(void) splx(s);
+			ip_unlock(port);
+			/* XXX thread might disappear on us now? */
+#if	MACH_FIXPRI
+			if (thread->policy == POLICY_FIXEDPRI) {
+			    myprocessor = current_processor();
+			    myprocessor->quantum = thread->sched_data;
+			    myprocessor->first_quantum = TRUE;
+			}
+#endif	/* MACH_FIXPRI */
+			counter(c_thread_switch_handoff++);
+			thread_run(thread_switch_continue, thread);
+			/*
+			 *  Restore depressed priority
+			 */
+			if (cur_thread->depress_priority >= 0)
+				(void) thread_depress_abort(cur_thread);
+
+			return(KERN_SUCCESS);
+		}
+		thread_unlock(thread);
+		(void) splx(s);
+	    }
+	    ip_unlock(port);
+    }
+#endif /* not MIGRATING_THREADS */
+
+    /*
+     *	No handoff hint supplied, or hint was wrong.  Call thread_block() in
+     *	hopes of running something else.  If nothing else is runnable,
+     *	thread_block will detect this.  WARNING: thread_switch with no
+     *	option will not do anything useful if the thread calling it is the
+     *	highest priority thread (can easily happen with a collection
+     *	of timesharing threads).
+     */
+#if	NCPUS > 1
+    myprocessor = current_processor();
+    if (myprocessor->processor_set->runq.count > 0 ||
+	myprocessor->runq.count > 0)
+#endif	/* NCPUS > 1 */
+    {
+	counter(c_thread_switch_block++);
+	thread_block(thread_switch_continue);
+    }
+
+    /*
+     *  Restore depressed priority
+     */
+    if (cur_thread->depress_priority >= 0)
+	(void) thread_depress_abort(cur_thread);
+    return(KERN_SUCCESS);
+}
+
+/*
+ *	thread_depress_priority
+ *
+ *	Depress thread's priority to lowest possible for specified period.
+ *	Intended for use when thread wants a lock but doesn't know which
+ *	other thread is holding it.  As with thread_switch, fixed
+ *	priority threads get exactly what they asked for.  Users access
+ *	this by the SWITCH_OPTION_DEPRESS option to thread_switch.  A Time
+ *      of zero will result in no timeout being scheduled.
+ */
+void
+thread_depress_priority(thread, depress_time)
+register thread_t thread;
+mach_msg_timeout_t depress_time;
+{
+    unsigned int ticks;
+    spl_t	s;
+
+    /* convert from milliseconds to ticks */
+    ticks = convert_ipc_timeout_to_ticks(depress_time);
+
+    s = splsched();
+    thread_lock(thread);
+
+    /*
+     *	If thread is already depressed, override previous depression.
+     */
+    reset_timeout_check(&thread->depress_timer);
+
+    /*
+     *	Save current priority, then set priority and
+     *	sched_pri to their lowest possible values.
+     */
+    thread->depress_priority = thread->priority;
+    thread->priority = 31;
+    thread->sched_pri = 31;
+    if (ticks != 0)
+	set_timeout(&thread->depress_timer, ticks);
+
+    thread_unlock(thread);
+    (void) splx(s);
+}
+
+/*
+ *	thread_depress_timeout:
+ *
+ *	Timeout routine for priority depression.
+ */
+void
+thread_depress_timeout(thread)
+register thread_t thread;
+{
+    spl_t	s;
+
+    s = splsched();
+    thread_lock(thread);
+
+    /*
+     *	If we lose a race with thread_depress_abort,
+     *	then depress_priority might be -1.
+     */
+
+    if (thread->depress_priority >= 0) {
+	thread->priority = thread->depress_priority;
+	thread->depress_priority = -1;
+	compute_priority(thread, FALSE);
+    }
+
+    thread_unlock(thread);
+    (void) splx(s);
+}
+
+/*
+ *	thread_depress_abort:
+ *
+ *	Prematurely abort priority depression if there is one.
+ */
+kern_return_t
+thread_depress_abort(thread)
+register thread_t	thread;
+{
+    spl_t	s;
+
+    if (thread == THREAD_NULL)
+	return(KERN_INVALID_ARGUMENT);
+
+    s = splsched();
+    thread_lock(thread);
+
+    /*
+     *	Only restore priority if thread is depressed.
+     */
+    if (thread->depress_priority >= 0) {
+	reset_timeout_check(&thread->depress_timer);
+	thread->priority = thread->depress_priority;
+	thread->depress_priority = -1;
+	compute_priority(thread, FALSE);
+    }
+
+    thread_unlock(thread);
+    (void) splx(s);
+    return(KERN_SUCCESS);
+}
diff -Npur gnumach.old/vm/vm_fault.c gnumach.new/vm/vm_fault.c
--- gnumach.old/vm/vm_fault.c	2001-04-05 03:39:20.000000000 -0300
+++ gnumach.new/vm/vm_fault.c	2006-04-05 23:36:15.000000000 -0300
@@ -243,7 +243,6 @@ vm_fault_return_t vm_fault_page(first_ob
 	boolean_t	look_for_page;
 	vm_prot_t	access_required;
 
-#ifdef CONTINUATIONS
 	if (resume) {
 		register vm_fault_state_t *state =
 			(vm_fault_state_t *) current_thread()->ith_other;
@@ -257,10 +256,6 @@ vm_fault_return_t vm_fault_page(first_ob
 		access_required = state->vmfp_access;
 		goto after_thread_block;
 	}
-#else /* not CONTINUATIONS */
-	assert(continuation == 0);
-	assert(!resume);
-#endif /* not CONTINUATIONS */
 
 	vm_stat_sample(SAMPLED_PC_VM_FAULTS_ANY);
 	vm_stat.faults++;		/* needs lock XXX */
@@ -365,7 +360,6 @@ vm_fault_return_t vm_fault_page(first_ob
 
 				PAGE_ASSERT_WAIT(m, interruptible);
 				vm_object_unlock(object);
-#ifdef CONTINUATIONS
 				if (continuation != (void (*)()) 0) {
 					register vm_fault_state_t *state =
 						(vm_fault_state_t *) current_thread()->ith_other;
@@ -387,7 +381,6 @@ vm_fault_return_t vm_fault_page(first_ob
 					counter(c_vm_fault_page_block_busy_user++);
 					thread_block(continuation);
 				} else
-#endif /* CONTINUATIONS */
 				{
 					counter(c_vm_fault_page_block_busy_kernel++);
 					thread_block((void (*)()) 0);
@@ -1099,7 +1092,6 @@ vm_fault_return_t vm_fault_page(first_ob
     block_and_backoff:
 	vm_fault_cleanup(object, first_m);
 
-#ifdef CONTINUATIONS
 	if (continuation != (void (*)()) 0) {
 		register vm_fault_state_t *state =
 			(vm_fault_state_t *) current_thread()->ith_other;
@@ -1114,7 +1106,6 @@ vm_fault_return_t vm_fault_page(first_ob
 		counter(c_vm_fault_page_block_backoff_user++);
 		thread_block(continuation);
 	} else
-#endif /* CONTINUATIONS */
 	{
 		counter(c_vm_fault_page_block_backoff_kernel++);
 		thread_block((void (*)()) 0);
@@ -1148,7 +1139,6 @@ vm_fault_return_t vm_fault_page(first_ob
  *		and deallocated when leaving vm_fault.
  */
 
-#ifdef CONTINUATIONS
 void
 vm_fault_continue()
 {
@@ -1162,7 +1152,6 @@ vm_fault_continue()
 			TRUE, state->vmf_continuation);
 	/*NOTREACHED*/
 }
-#endif /* CONTINUATIONS */
 
 kern_return_t vm_fault(map, vaddr, fault_type, change_wiring,
 		       resume, continuation)
@@ -1186,7 +1175,6 @@ kern_return_t vm_fault(map, vaddr, fault
 	register
 	vm_page_t		m;	/* Fast access to result_page */
 
-#ifdef CONTINUATIONS
 	if (resume) {
 		register vm_fault_state_t *state =
 			(vm_fault_state_t *) current_thread()->ith_other;
@@ -1229,10 +1217,6 @@ kern_return_t vm_fault(map, vaddr, fault
 		current_thread()->ith_other = state;
 
 	}
-#else /* not CONTINUATIONS */
-	assert(continuation == 0);
-	assert(!resume);
-#endif /* not CONTINUATIONS */
 
     RetryFault: ;
 
@@ -1267,7 +1251,6 @@ kern_return_t vm_fault(map, vaddr, fault
 	object->ref_count++;
 	vm_object_paging_begin(object);
 
-#ifdef CONTINUATIONS
 	if (continuation != (void (*)()) 0) {
 		register vm_fault_state_t *state =
 			(vm_fault_state_t *) current_thread()->ith_other;
@@ -1294,7 +1277,6 @@ kern_return_t vm_fault(map, vaddr, fault
 				   &prot, &result_page, &top_page,
 				   FALSE, vm_fault_continue);
 	} else
-#endif /* CONTINUATIONS */
 	{
 		kr = vm_fault_page(object, offset, fault_type,
 				   (change_wiring && !wired), !change_wiring,
@@ -1323,7 +1305,6 @@ kern_return_t vm_fault(map, vaddr, fault
 			kr = KERN_SUCCESS;
 			goto done;
 		case VM_FAULT_MEMORY_SHORTAGE:
-#ifdef CONTINUATIONS
 			if (continuation != (void (*)()) 0) {
 				register vm_fault_state_t *state =
 					(vm_fault_state_t *) current_thread()->ith_other;
@@ -1342,7 +1323,6 @@ kern_return_t vm_fault(map, vaddr, fault
 
 				VM_PAGE_WAIT(vm_fault_continue);
 			} else
-#endif /* CONTINUATIONS */
 				VM_PAGE_WAIT((void (*)()) 0);
 			goto RetryFault;
 		case VM_FAULT_FICTITIOUS_SHORTAGE:
@@ -1508,7 +1488,6 @@ kern_return_t vm_fault(map, vaddr, fault
 #undef	RELEASE_PAGE
 
     done:
-#ifdef CONTINUATIONS
 	if (continuation != (void (*)()) 0) {
 		register vm_fault_state_t *state =
 			(vm_fault_state_t *) current_thread()->ith_other;
@@ -1517,7 +1496,6 @@ kern_return_t vm_fault(map, vaddr, fault
 		(*continuation)(kr);
 		/*NOTREACHED*/
 	}
-#endif /* CONTINUATIONS */
 
 	return(kr);
 }
diff -Npur gnumach.old/vm/vm_fault.c.~1.3.~ gnumach.new/vm/vm_fault.c.~1.3.~
--- gnumach.old/vm/vm_fault.c.~1.3.~	1969-12-31 21:00:00.000000000 -0300
+++ gnumach.new/vm/vm_fault.c.~1.3.~	2001-04-05 03:39:20.000000000 -0300
@@ -0,0 +1,2182 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1994,1990,1989,1988,1987 Carnegie Mellon University.
+ * Copyright (c) 1993,1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL).
+ * 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, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
+ * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
+ * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
+ * THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ *	File:	vm_fault.c
+ *	Author:	Avadis Tevanian, Jr., Michael Wayne Young
+ *
+ *	Page fault handling module.
+ */
+#include <mach_pagemap.h>
+#include <mach_kdb.h>
+#include <mach_pcsample.h>
+
+
+#include <vm/vm_fault.h>
+#include <mach/kern_return.h>
+#include <mach/message.h>	/* for error codes */
+#include <kern/counters.h>
+#include <kern/thread.h>
+#include <kern/sched_prim.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/pmap.h>
+#include <mach/vm_statistics.h>
+#include <vm/vm_pageout.h>
+#include <mach/vm_param.h>
+#include <mach/memory_object.h>
+#include "memory_object_user.h"
+				/* For memory_object_data_{request,unlock} */
+#include <kern/mach_param.h>
+#include <kern/macro_help.h>
+#include <kern/zalloc.h>
+
+#if	MACH_PCSAMPLE
+#include <kern/pc_sample.h>
+#endif
+
+
+
+/*
+ *	State needed by vm_fault_continue.
+ *	This is a little hefty to drop directly
+ *	into the thread structure.
+ */
+typedef struct vm_fault_state {
+	struct vm_map *vmf_map;
+	vm_offset_t vmf_vaddr;
+	vm_prot_t vmf_fault_type;
+	boolean_t vmf_change_wiring;
+	void (*vmf_continuation)();
+	vm_map_version_t vmf_version;
+	boolean_t vmf_wired;
+	struct vm_object *vmf_object;
+	vm_offset_t vmf_offset;
+	vm_prot_t vmf_prot;
+
+	boolean_t vmfp_backoff;
+	struct vm_object *vmfp_object;
+	vm_offset_t vmfp_offset;
+	struct vm_page *vmfp_first_m;
+	vm_prot_t vmfp_access;
+} vm_fault_state_t;
+
+zone_t		vm_fault_state_zone = 0;
+
+int		vm_object_absent_max = 50;
+
+int		vm_fault_debug = 0;
+
+boolean_t	vm_fault_dirty_handling = FALSE;
+boolean_t	vm_fault_interruptible = TRUE;
+
+boolean_t	software_reference_bits = TRUE;
+
+#if	MACH_KDB
+extern struct db_watchpoint *db_watchpoint_list;
+#endif	/* MACH_KDB */
+
+/*
+ *	Routine:	vm_fault_init
+ *	Purpose:
+ *		Initialize our private data structures.
+ */
+void vm_fault_init()
+{
+	vm_fault_state_zone = zinit(sizeof(vm_fault_state_t),
+				    THREAD_MAX * sizeof(vm_fault_state_t),
+				    sizeof(vm_fault_state_t),
+				    0, "vm fault state");
+}
+
+/*
+ *	Routine:	vm_fault_cleanup
+ *	Purpose:
+ *		Clean up the result of vm_fault_page.
+ *	Results:
+ *		The paging reference for "object" is released.
+ *		"object" is unlocked.
+ *		If "top_page" is not null,  "top_page" is
+ *		freed and the paging reference for the object
+ *		containing it is released.
+ *
+ *	In/out conditions:
+ *		"object" must be locked.
+ */
+void
+vm_fault_cleanup(object, top_page)
+	register vm_object_t	object;
+	register vm_page_t	top_page;
+{
+	vm_object_paging_end(object);
+	vm_object_unlock(object);
+
+	if (top_page != VM_PAGE_NULL) {
+	    object = top_page->object;
+	    vm_object_lock(object);
+	    VM_PAGE_FREE(top_page);
+	    vm_object_paging_end(object);
+	    vm_object_unlock(object);
+	}
+}
+
+
+#if	MACH_PCSAMPLE
+/*
+ *	Do PC sampling on current thread, assuming
+ *	that it is the thread taking this page fault.
+ *
+ *	Must check for THREAD_NULL, since faults
+ *	can occur before threads are running.
+ */
+
+#define	vm_stat_sample(flavor) \
+    MACRO_BEGIN \
+      thread_t _thread_ = current_thread(); \
+ \
+      if (_thread_ != THREAD_NULL) \
+	  take_pc_sample_macro(_thread_, (flavor)); \
+    MACRO_END
+
+#else
+#define	vm_stat_sample(x)
+#endif	/* MACH_PCSAMPLE */
+
+
+
+/*
+ *	Routine:	vm_fault_page
+ *	Purpose:
+ *		Find the resident page for the virtual memory
+ *		specified by the given virtual memory object
+ *		and offset.
+ *	Additional arguments:
+ *		The required permissions for the page is given
+ *		in "fault_type".  Desired permissions are included
+ *		in "protection".
+ *
+ *		If the desired page is known to be resident (for
+ *		example, because it was previously wired down), asserting
+ *		the "unwiring" parameter will speed the search.
+ *
+ *		If the operation can be interrupted (by thread_abort
+ *		or thread_terminate), then the "interruptible"
+ *		parameter should be asserted.
+ *
+ *	Results:
+ *		The page containing the proper data is returned
+ *		in "result_page".
+ *
+ *	In/out conditions:
+ *		The source object must be locked and referenced,
+ *		and must donate one paging reference.  The reference
+ *		is not affected.  The paging reference and lock are
+ *		consumed.
+ *
+ *		If the call succeeds, the object in which "result_page"
+ *		resides is left locked and holding a paging reference.
+ *		If this is not the original object, a busy page in the
+ *		original object is returned in "top_page", to prevent other
+ *		callers from pursuing this same data, along with a paging
+ *		reference for the original object.  The "top_page" should
+ *		be destroyed when this guarantee is no longer required.
+ *		The "result_page" is also left busy.  It is not removed
+ *		from the pageout queues.
+ */
+vm_fault_return_t vm_fault_page(first_object, first_offset,
+				fault_type, must_be_resident, interruptible,
+				protection,
+				result_page, top_page,
+				resume, continuation)
+ /* Arguments: */
+	vm_object_t	first_object;	/* Object to begin search */
+	vm_offset_t	first_offset;	/* Offset into object */
+	vm_prot_t	fault_type;	/* What access is requested */
+	boolean_t	must_be_resident;/* Must page be resident? */
+	boolean_t	interruptible;	/* May fault be interrupted? */
+ /* Modifies in place: */
+	vm_prot_t	*protection;	/* Protection for mapping */
+ /* Returns: */
+	vm_page_t	*result_page;	/* Page found, if successful */
+	vm_page_t	*top_page;	/* Page in top object, if
+					 * not result_page.
+					 */
+ /* More arguments: */
+	boolean_t	resume;		/* We are restarting. */
+	void		(*continuation)(); /* Continuation for blocking. */
+{
+	register
+	vm_page_t	m;
+	register
+	vm_object_t	object;
+	register
+	vm_offset_t	offset;
+	vm_page_t	first_m;
+	vm_object_t	next_object;
+	vm_object_t	copy_object;
+	boolean_t	look_for_page;
+	vm_prot_t	access_required;
+
+#ifdef CONTINUATIONS
+	if (resume) {
+		register vm_fault_state_t *state =
+			(vm_fault_state_t *) current_thread()->ith_other;
+
+		if (state->vmfp_backoff)
+			goto after_block_and_backoff;
+
+		object = state->vmfp_object;
+		offset = state->vmfp_offset;
+		first_m = state->vmfp_first_m;
+		access_required = state->vmfp_access;
+		goto after_thread_block;
+	}
+#else /* not CONTINUATIONS */
+	assert(continuation == 0);
+	assert(!resume);
+#endif /* not CONTINUATIONS */
+
+	vm_stat_sample(SAMPLED_PC_VM_FAULTS_ANY);
+	vm_stat.faults++;		/* needs lock XXX */
+
+/*
+ *	Recovery actions
+ */
+#define RELEASE_PAGE(m)					\
+	MACRO_BEGIN					\
+	PAGE_WAKEUP_DONE(m);				\
+	vm_page_lock_queues();				\
+	if (!m->active && !m->inactive)			\
+		vm_page_activate(m);			\
+	vm_page_unlock_queues();			\
+	MACRO_END
+
+	if (vm_fault_dirty_handling
+#if	MACH_KDB
+		/*
+		 *	If there are watchpoints set, then
+		 *	we don't want to give away write permission
+		 *	on a read fault.  Make the task write fault,
+		 *	so that the watchpoint code notices the access.
+		 */
+	    || db_watchpoint_list
+#endif	/* MACH_KDB */
+	    ) {
+		/*
+		 *	If we aren't asking for write permission,
+		 *	then don't give it away.  We're using write
+		 *	faults to set the dirty bit.
+		 */
+		if (!(fault_type & VM_PROT_WRITE))
+			*protection &= ~VM_PROT_WRITE;
+	}
+
+	if (!vm_fault_interruptible)
+		interruptible = FALSE;
+
+	/*
+	 *	INVARIANTS (through entire routine):
+	 *
+	 *	1)	At all times, we must either have the object
+	 *		lock or a busy page in some object to prevent
+	 *		some other thread from trying to bring in
+	 *		the same page.
+	 *
+	 *		Note that we cannot hold any locks during the
+	 *		pager access or when waiting for memory, so
+	 *		we use a busy page then.
+	 *
+	 *		Note also that we aren't as concerned about more than
+	 *		one thread attempting to memory_object_data_unlock
+	 *		the same page at once, so we don't hold the page
+	 *		as busy then, but do record the highest unlock
+	 *		value so far.  [Unlock requests may also be delivered
+	 *		out of order.]
+	 *
+	 *	2)	To prevent another thread from racing us down the
+	 *		shadow chain and entering a new page in the top
+	 *		object before we do, we must keep a busy page in
+	 *		the top object while following the shadow chain.
+	 *
+	 *	3)	We must increment paging_in_progress on any object
+	 *		for which we have a busy page, to prevent
+	 *		vm_object_collapse from removing the busy page
+	 *		without our noticing.
+	 *
+	 *	4)	We leave busy pages on the pageout queues.
+	 *		If the pageout daemon comes across a busy page,
+	 *		it will remove the page from the pageout queues.
+	 */
+
+	/*
+	 *	Search for the page at object/offset.
+	 */
+
+	object = first_object;
+	offset = first_offset;
+	first_m = VM_PAGE_NULL;
+	access_required = fault_type;
+
+	/*
+	 *	See whether this page is resident
+	 */
+
+	while (TRUE) {
+		m = vm_page_lookup(object, offset);
+		if (m != VM_PAGE_NULL) {
+			/*
+			 *	If the page is being brought in,
+			 *	wait for it and then retry.
+			 *
+			 *	A possible optimization: if the page
+			 *	is known to be resident, we can ignore
+			 *	pages that are absent (regardless of
+			 *	whether they're busy).
+			 */
+
+			if (m->busy) {
+				kern_return_t	wait_result;
+
+				PAGE_ASSERT_WAIT(m, interruptible);
+				vm_object_unlock(object);
+#ifdef CONTINUATIONS
+				if (continuation != (void (*)()) 0) {
+					register vm_fault_state_t *state =
+						(vm_fault_state_t *) current_thread()->ith_other;
+
+					/*
+					 *	Save variables in case
+					 *	thread_block discards
+					 *	our kernel stack.
+					 */
+
+					state->vmfp_backoff = FALSE;
+					state->vmfp_object = object;
+					state->vmfp_offset = offset;
+					state->vmfp_first_m = first_m;
+					state->vmfp_access =
+						access_required;
+					state->vmf_prot = *protection;
+
+					counter(c_vm_fault_page_block_busy_user++);
+					thread_block(continuation);
+				} else
+#endif /* CONTINUATIONS */
+				{
+					counter(c_vm_fault_page_block_busy_kernel++);
+					thread_block((void (*)()) 0);
+				}
+			    after_thread_block:
+				wait_result = current_thread()->wait_result;
+				vm_object_lock(object);
+				if (wait_result != THREAD_AWAKENED) {
+					vm_fault_cleanup(object, first_m);
+					if (wait_result == THREAD_RESTART)
+						return(VM_FAULT_RETRY);
+					else
+						return(VM_FAULT_INTERRUPTED);
+				}
+				continue;
+			}
+
+			/*
+			 *	If the page is in error, give up now.
+			 */
+
+			if (m->error) {
+				VM_PAGE_FREE(m);
+				vm_fault_cleanup(object, first_m);
+				return(VM_FAULT_MEMORY_ERROR);
+			}
+
+			/*
+			 *	If the page isn't busy, but is absent,
+			 *	then it was deemed "unavailable".
+			 */
+
+			if (m->absent) {
+				/*
+				 * Remove the non-existent page (unless it's
+				 * in the top object) and move on down to the
+				 * next object (if there is one).
+				 */
+
+				offset += object->shadow_offset;
+				access_required = VM_PROT_READ;
+				next_object = object->shadow;
+				if (next_object == VM_OBJECT_NULL) {
+					vm_page_t real_m;
+
+					assert(!must_be_resident);
+
+					/*
+					 * Absent page at bottom of shadow
+					 * chain; zero fill the page we left
+					 * busy in the first object, and flush
+					 * the absent page.  But first we
+					 * need to allocate a real page.
+					 */
+
+					real_m = vm_page_grab(!object->internal);
+					if (real_m == VM_PAGE_NULL) {
+						vm_fault_cleanup(object, first_m);
+						return(VM_FAULT_MEMORY_SHORTAGE);
+					}
+
+					if (object != first_object) {
+						VM_PAGE_FREE(m);
+						vm_object_paging_end(object);
+						vm_object_unlock(object);
+						object = first_object;
+						offset = first_offset;
+						m = first_m;
+						first_m = VM_PAGE_NULL;
+						vm_object_lock(object);
+					}
+
+					VM_PAGE_FREE(m);
+					assert(real_m->busy);
+					vm_page_lock_queues();
+					vm_page_insert(real_m, object, offset);
+					vm_page_unlock_queues();
+					m = real_m;
+
+					/*
+					 *  Drop the lock while zero filling
+					 *  page.  Then break because this
+					 *  is the page we wanted.  Checking
+					 *  the page lock is a waste of time;
+					 *  this page was either absent or
+					 *  newly allocated -- in both cases
+					 *  it can't be page locked by a pager.
+					 */
+					vm_object_unlock(object);
+
+					vm_page_zero_fill(m);
+
+					vm_stat_sample(SAMPLED_PC_VM_ZFILL_FAULTS);
+
+					vm_stat.zero_fill_count++;
+					vm_object_lock(object);
+					pmap_clear_modify(m->phys_addr);
+					break;
+				} else {
+					if (must_be_resident) {
+						vm_object_paging_end(object);
+					} else if (object != first_object) {
+						vm_object_paging_end(object);
+						VM_PAGE_FREE(m);
+					} else {
+						first_m = m;
+						m->absent = FALSE;
+						vm_object_absent_release(object);
+						m->busy = TRUE;
+
+						vm_page_lock_queues();
+						VM_PAGE_QUEUES_REMOVE(m);
+						vm_page_unlock_queues();
+					}
+					vm_object_lock(next_object);
+					vm_object_unlock(object);
+					object = next_object;
+					vm_object_paging_begin(object);
+					continue;
+				}
+			}
+
+			/*
+			 *	If the desired access to this page has
+			 *	been locked out, request that it be unlocked.
+			 */
+
+			if (access_required & m->page_lock) {
+				if ((access_required & m->unlock_request) != access_required) {
+					vm_prot_t	new_unlock_request;
+					kern_return_t	rc;
+
+					if (!object->pager_ready) {
+						vm_object_assert_wait(object,
+							VM_OBJECT_EVENT_PAGER_READY,
+							interruptible);
+						goto block_and_backoff;
+					}
+
+					new_unlock_request = m->unlock_request =
+						(access_required | m->unlock_request);
+					vm_object_unlock(object);
+					if ((rc = memory_object_data_unlock(
+						object->pager,
+						object->pager_request,
+						offset + object->paging_offset,
+						PAGE_SIZE,
+						new_unlock_request))
+					     != KERN_SUCCESS) {
+					     	printf("vm_fault: memory_object_data_unlock failed\n");
+						vm_object_lock(object);
+						vm_fault_cleanup(object, first_m);
+						return((rc == MACH_SEND_INTERRUPTED) ?
+							VM_FAULT_INTERRUPTED :
+							VM_FAULT_MEMORY_ERROR);
+					}
+					vm_object_lock(object);
+					continue;
+				}
+
+				PAGE_ASSERT_WAIT(m, interruptible);
+				goto block_and_backoff;
+			}
+
+			/*
+			 *	We mark the page busy and leave it on
+			 *	the pageout queues.  If the pageout
+			 *	deamon comes across it, then it will
+			 *	remove the page.
+			 */
+
+			if (!software_reference_bits) {
+				vm_page_lock_queues();
+				if (m->inactive)  {
+				    	vm_stat_sample(SAMPLED_PC_VM_REACTIVATION_FAULTS);
+					vm_stat.reactivations++;
+				}
+
+				VM_PAGE_QUEUES_REMOVE(m);
+				vm_page_unlock_queues();
+			}
+
+			assert(!m->busy);
+			m->busy = TRUE;
+			assert(!m->absent);
+			break;
+		}
+
+		look_for_page =
+			(object->pager_created)
+#if	MACH_PAGEMAP
+			&& (vm_external_state_get(object->existence_info, offset + object->paging_offset) !=
+			 VM_EXTERNAL_STATE_ABSENT)
+#endif	/* MACH_PAGEMAP */
+			 ;
+
+		if ((look_for_page || (object == first_object))
+				 && !must_be_resident) {
+			/*
+			 *	Allocate a new page for this object/offset
+			 *	pair.
+			 */
+
+			m = vm_page_grab_fictitious();
+			if (m == VM_PAGE_NULL) {
+				vm_fault_cleanup(object, first_m);
+				return(VM_FAULT_FICTITIOUS_SHORTAGE);
+			}
+
+			vm_page_lock_queues();
+			vm_page_insert(m, object, offset);
+			vm_page_unlock_queues();
+		}
+
+		if (look_for_page && !must_be_resident) {
+			kern_return_t	rc;
+
+			/*
+			 *	If the memory manager is not ready, we
+			 *	cannot make requests.
+			 */
+			if (!object->pager_ready) {
+				vm_object_assert_wait(object,
+					VM_OBJECT_EVENT_PAGER_READY,
+					interruptible);
+				VM_PAGE_FREE(m);
+				goto block_and_backoff;
+			}
+
+			if (object->internal) {
+				/*
+				 *	Requests to the default pager
+				 *	must reserve a real page in advance,
+				 *	because the pager's data-provided
+				 *	won't block for pages.
+				 */
+
+				if (m->fictitious && !vm_page_convert(m, FALSE)) {
+					VM_PAGE_FREE(m);
+					vm_fault_cleanup(object, first_m);
+					return(VM_FAULT_MEMORY_SHORTAGE);
+				}
+			} else if (object->absent_count >
+						vm_object_absent_max) {
+				/*
+				 *	If there are too many outstanding page
+				 *	requests pending on this object, we
+				 *	wait for them to be resolved now.
+				 */
+
+				vm_object_absent_assert_wait(object, interruptible);
+				VM_PAGE_FREE(m);
+				goto block_and_backoff;
+			}
+
+			/*
+			 *	Indicate that the page is waiting for data
+			 *	from the memory manager.
+			 */
+
+			m->absent = TRUE;
+			object->absent_count++;
+
+			/*
+			 *	We have a busy page, so we can
+			 *	release the object lock.
+			 */
+			vm_object_unlock(object);
+
+			/*
+			 *	Call the memory manager to retrieve the data.
+			 */
+
+			vm_stat.pageins++;
+		    	vm_stat_sample(SAMPLED_PC_VM_PAGEIN_FAULTS);
+
+			if ((rc = memory_object_data_request(object->pager,
+				object->pager_request,
+				m->offset + object->paging_offset,
+				PAGE_SIZE, access_required)) != KERN_SUCCESS) {
+				if (rc != MACH_SEND_INTERRUPTED)
+					printf("%s(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) failed, %d\n",
+						"memory_object_data_request",
+						object->pager,
+						object->pager_request,
+						m->offset + object->paging_offset,
+						PAGE_SIZE, access_required, rc);
+				/*
+				 *	Don't want to leave a busy page around,
+				 *	but the data request may have blocked,
+				 *	so check if it's still there and busy.
+				 */
+				vm_object_lock(object);
+				if (m == vm_page_lookup(object,offset) &&
+				    m->absent && m->busy)
+					VM_PAGE_FREE(m);
+				vm_fault_cleanup(object, first_m);
+				return((rc == MACH_SEND_INTERRUPTED) ?
+					VM_FAULT_INTERRUPTED :
+					VM_FAULT_MEMORY_ERROR);
+			}
+
+			/*
+			 * Retry with same object/offset, since new data may
+			 * be in a different page (i.e., m is meaningless at
+			 * this point).
+			 */
+			vm_object_lock(object);
+			continue;
+		}
+
+		/*
+		 * For the XP system, the only case in which we get here is if
+		 * object has no pager (or unwiring).  If the pager doesn't
+		 * have the page this is handled in the m->absent case above
+		 * (and if you change things here you should look above).
+		 */
+		if (object == first_object)
+			first_m = m;
+		else
+		{
+			assert(m == VM_PAGE_NULL);
+		}
+
+		/*
+		 *	Move on to the next object.  Lock the next
+		 *	object before unlocking the current one.
+		 */
+		access_required = VM_PROT_READ;
+
+		offset += object->shadow_offset;
+		next_object = object->shadow;
+		if (next_object == VM_OBJECT_NULL) {
+			assert(!must_be_resident);
+
+			/*
+			 *	If there's no object left, fill the page
+			 *	in the top object with zeros.  But first we
+			 *	need to allocate a real page.
+			 */
+
+			if (object != first_object) {
+				vm_object_paging_end(object);
+				vm_object_unlock(object);
+
+				object = first_object;
+				offset = first_offset;
+				vm_object_lock(object);
+			}
+
+			m = first_m;
+			assert(m->object == object);
+			first_m = VM_PAGE_NULL;
+
+			if (m->fictitious && !vm_page_convert(m, !object->internal)) {
+				VM_PAGE_FREE(m);
+				vm_fault_cleanup(object, VM_PAGE_NULL);
+				return(VM_FAULT_MEMORY_SHORTAGE);
+			}
+
+			vm_object_unlock(object);
+			vm_page_zero_fill(m);
+			vm_stat_sample(SAMPLED_PC_VM_ZFILL_FAULTS);
+			vm_stat.zero_fill_count++;
+			vm_object_lock(object);
+			pmap_clear_modify(m->phys_addr);
+			break;
+		}
+		else {
+			vm_object_lock(next_object);
+			if ((object != first_object) || must_be_resident)
+				vm_object_paging_end(object);
+			vm_object_unlock(object);
+			object = next_object;
+			vm_object_paging_begin(object);
+		}
+	}
+
+	/*
+	 *	PAGE HAS BEEN FOUND.
+	 *
+	 *	This page (m) is:
+	 *		busy, so that we can play with it;
+	 *		not absent, so that nobody else will fill it;
+	 *		possibly eligible for pageout;
+	 *
+	 *	The top-level page (first_m) is:
+	 *		VM_PAGE_NULL if the page was found in the
+	 *		 top-level object;
+	 *		busy, not absent, and ineligible for pageout.
+	 *
+	 *	The current object (object) is locked.  A paging
+	 *	reference is held for the current and top-level
+	 *	objects.
+	 */
+
+#if	EXTRA_ASSERTIONS
+	assert(m->busy && !m->absent);
+	assert((first_m == VM_PAGE_NULL) ||
+		(first_m->busy && !first_m->absent &&
+		 !first_m->active && !first_m->inactive));
+#endif	/* EXTRA_ASSERTIONS */
+
+	/*
+	 *	If the page is being written, but isn't
+	 *	already owned by the top-level object,
+	 *	we have to copy it into a new page owned
+	 *	by the top-level object.
+	 */
+
+	if (object != first_object) {
+	    	/*
+		 *	We only really need to copy if we
+		 *	want to write it.
+		 */
+
+	    	if (fault_type & VM_PROT_WRITE) {
+			vm_page_t copy_m;
+
+			assert(!must_be_resident);
+
+			/*
+			 *	If we try to collapse first_object at this
+			 *	point, we may deadlock when we try to get
+			 *	the lock on an intermediate object (since we
+			 *	have the bottom object locked).  We can't
+			 *	unlock the bottom object, because the page
+			 *	we found may move (by collapse) if we do.
+			 *
+			 *	Instead, we first copy the page.  Then, when
+			 *	we have no more use for the bottom object,
+			 *	we unlock it and try to collapse.
+			 *
+			 *	Note that we copy the page even if we didn't
+			 *	need to... that's the breaks.
+			 */
+
+			/*
+			 *	Allocate a page for the copy
+			 */
+			copy_m = vm_page_grab(!first_object->internal);
+			if (copy_m == VM_PAGE_NULL) {
+				RELEASE_PAGE(m);
+				vm_fault_cleanup(object, first_m);
+				return(VM_FAULT_MEMORY_SHORTAGE);
+			}
+
+			vm_object_unlock(object);
+			vm_page_copy(m, copy_m);
+			vm_object_lock(object);
+
+			/*
+			 *	If another map is truly sharing this
+			 *	page with us, we have to flush all
+			 *	uses of the original page, since we
+			 *	can't distinguish those which want the
+			 *	original from those which need the
+			 *	new copy.
+			 *
+			 *	XXXO If we know that only one map has
+			 *	access to this page, then we could
+			 *	avoid the pmap_page_protect() call.
+			 */
+
+			vm_page_lock_queues();
+			vm_page_deactivate(m);
+			pmap_page_protect(m->phys_addr, VM_PROT_NONE);
+			vm_page_unlock_queues();
+
+			/*
+			 *	We no longer need the old page or object.
+			 */
+
+			PAGE_WAKEUP_DONE(m);
+			vm_object_paging_end(object);
+			vm_object_unlock(object);
+
+			vm_stat.cow_faults++;
+			vm_stat_sample(SAMPLED_PC_VM_COW_FAULTS);
+			object = first_object;
+			offset = first_offset;
+
+			vm_object_lock(object);
+			VM_PAGE_FREE(first_m);
+			first_m = VM_PAGE_NULL;
+			assert(copy_m->busy);
+			vm_page_lock_queues();
+			vm_page_insert(copy_m, object, offset);
+			vm_page_unlock_queues();
+			m = copy_m;
+
+			/*
+			 *	Now that we've gotten the copy out of the
+			 *	way, let's try to collapse the top object.
+			 *	But we have to play ugly games with
+			 *	paging_in_progress to do that...
+			 */
+
+			vm_object_paging_end(object);
+			vm_object_collapse(object);
+			vm_object_paging_begin(object);
+		}
+		else {
+		    	*protection &= (~VM_PROT_WRITE);
+		}
+	}
+
+	/*
+	 *	Now check whether the page needs to be pushed into the
+	 *	copy object.  The use of asymmetric copy on write for
+	 *	shared temporary objects means that we may do two copies to
+	 *	satisfy the fault; one above to get the page from a
+	 *	shadowed object, and one here to push it into the copy.
+	 */
+
+	while ((copy_object = first_object->copy) != VM_OBJECT_NULL) {
+		vm_offset_t	copy_offset;
+		vm_page_t	copy_m;
+
+		/*
+		 *	If the page is being written, but hasn't been
+		 *	copied to the copy-object, we have to copy it there.
+		 */
+
+		if ((fault_type & VM_PROT_WRITE) == 0) {
+			*protection &= ~VM_PROT_WRITE;
+			break;
+		}
+
+		/*
+		 *	If the page was guaranteed to be resident,
+		 *	we must have already performed the copy.
+		 */
+
+		if (must_be_resident)
+			break;
+
+		/*
+		 *	Try to get the lock on the copy_object.
+		 */
+		if (!vm_object_lock_try(copy_object)) {
+			vm_object_unlock(object);
+
+			simple_lock_pause();	/* wait a bit */
+
+			vm_object_lock(object);
+			continue;
+		}
+
+		/*
+		 *	Make another reference to the copy-object,
+		 *	to keep it from disappearing during the
+		 *	copy.
+		 */
+		assert(copy_object->ref_count > 0);
+		copy_object->ref_count++;
+
+		/*
+		 *	Does the page exist in the copy?
+		 */
+		copy_offset = first_offset - copy_object->shadow_offset;
+		copy_m = vm_page_lookup(copy_object, copy_offset);
+		if (copy_m != VM_PAGE_NULL) {
+			if (copy_m->busy) {
+				/*
+				 *	If the page is being brought
+				 *	in, wait for it and then retry.
+				 */
+				PAGE_ASSERT_WAIT(copy_m, interruptible);
+				RELEASE_PAGE(m);
+				copy_object->ref_count--;
+				assert(copy_object->ref_count > 0);
+				vm_object_unlock(copy_object);
+				goto block_and_backoff;
+			}
+		}
+		else {
+			/*
+			 *	Allocate a page for the copy
+			 */
+			copy_m = vm_page_alloc(copy_object, copy_offset);
+			if (copy_m == VM_PAGE_NULL) {
+				RELEASE_PAGE(m);
+				copy_object->ref_count--;
+				assert(copy_object->ref_count > 0);
+				vm_object_unlock(copy_object);
+				vm_fault_cleanup(object, first_m);
+				return(VM_FAULT_MEMORY_SHORTAGE);
+			}
+
+			/*
+			 *	Must copy page into copy-object.
+			 */
+
+			vm_page_copy(m, copy_m);
+
+			/*
+			 *	If the old page was in use by any users
+			 *	of the copy-object, it must be removed
+			 *	from all pmaps.  (We can't know which
+			 *	pmaps use it.)
+			 */
+
+			vm_page_lock_queues();
+			pmap_page_protect(m->phys_addr, VM_PROT_NONE);
+			copy_m->dirty = TRUE;
+			vm_page_unlock_queues();
+
+			/*
+			 *	If there's a pager, then immediately
+			 *	page out this page, using the "initialize"
+			 *	option.  Else, we use the copy.
+			 */
+
+		 	if (!copy_object->pager_created) {
+				vm_page_lock_queues();
+				vm_page_activate(copy_m);
+				vm_page_unlock_queues();
+				PAGE_WAKEUP_DONE(copy_m);
+			} else {
+				/*
+				 *	The page is already ready for pageout:
+				 *	not on pageout queues and busy.
+				 *	Unlock everything except the
+				 *	copy_object itself.
+				 */
+
+				vm_object_unlock(object);
+
+				/*
+				 *	Write the page to the copy-object,
+				 *	flushing it from the kernel.
+				 */
+
+				vm_pageout_page(copy_m, TRUE, TRUE);
+
+				/*
+				 *	Since the pageout may have
+				 *	temporarily dropped the
+				 *	copy_object's lock, we
+				 *	check whether we'll have
+				 *	to deallocate the hard way.
+				 */
+
+				if ((copy_object->shadow != object) ||
+				    (copy_object->ref_count == 1)) {
+					vm_object_unlock(copy_object);
+					vm_object_deallocate(copy_object);
+					vm_object_lock(object);
+					continue;
+				}
+
+				/*
+				 *	Pick back up the old object's
+				 *	lock.  [It is safe to do so,
+				 *	since it must be deeper in the
+				 *	object tree.]
+				 */
+
+				vm_object_lock(object);
+			}
+
+			/*
+			 *	Because we're pushing a page upward
+			 *	in the object tree, we must restart
+			 *	any faults that are waiting here.
+			 *	[Note that this is an expansion of
+			 *	PAGE_WAKEUP that uses the THREAD_RESTART
+			 *	wait result].  Can't turn off the page's
+			 *	busy bit because we're not done with it.
+			 */
+
+			if (m->wanted) {
+				m->wanted = FALSE;
+				thread_wakeup_with_result((event_t) m,
+					THREAD_RESTART);
+			}
+		}
+
+		/*
+		 *	The reference count on copy_object must be
+		 *	at least 2: one for our extra reference,
+		 *	and at least one from the outside world
+		 *	(we checked that when we last locked
+		 *	copy_object).
+		 */
+		copy_object->ref_count--;
+		assert(copy_object->ref_count > 0);
+		vm_object_unlock(copy_object);
+
+		break;
+	}
+
+	*result_page = m;
+	*top_page = first_m;
+
+	/*
+	 *	If the page can be written, assume that it will be.
+	 *	[Earlier, we restrict the permission to allow write
+	 *	access only if the fault so required, so we don't
+	 *	mark read-only data as dirty.]
+	 */
+
+	if (vm_fault_dirty_handling && (*protection & VM_PROT_WRITE))
+		m->dirty = TRUE;
+
+	return(VM_FAULT_SUCCESS);
+
+    block_and_backoff:
+	vm_fault_cleanup(object, first_m);
+
+#ifdef CONTINUATIONS
+	if (continuation != (void (*)()) 0) {
+		register vm_fault_state_t *state =
+			(vm_fault_state_t *) current_thread()->ith_other;
+
+		/*
+		 *	Save variables in case we must restart.
+		 */
+
+		state->vmfp_backoff = TRUE;
+		state->vmf_prot = *protection;
+
+		counter(c_vm_fault_page_block_backoff_user++);
+		thread_block(continuation);
+	} else
+#endif /* CONTINUATIONS */
+	{
+		counter(c_vm_fault_page_block_backoff_kernel++);
+		thread_block((void (*)()) 0);
+	}
+    after_block_and_backoff:
+	if (current_thread()->wait_result == THREAD_AWAKENED)
+		return VM_FAULT_RETRY;
+	else
+		return VM_FAULT_INTERRUPTED;
+
+#undef	RELEASE_PAGE
+}
+
+/*
+ *	Routine:	vm_fault
+ *	Purpose:
+ *		Handle page faults, including pseudo-faults
+ *		used to change the wiring status of pages.
+ *	Returns:
+ *		If an explicit (expression) continuation is supplied,
+ *		then we call the continuation instead of returning.
+ *	Implementation:
+ *		Explicit continuations make this a little icky,
+ *		because it hasn't been rewritten to embrace CPS.
+ *		Instead, we have resume arguments for vm_fault and
+ *		vm_fault_page, to let continue the fault computation.
+ *
+ *		vm_fault and vm_fault_page save mucho state
+ *		in the moral equivalent of a closure.  The state
+ *		structure is allocated when first entering vm_fault
+ *		and deallocated when leaving vm_fault.
+ */
+
+#ifdef CONTINUATIONS
+void
+vm_fault_continue()
+{
+	register vm_fault_state_t *state =
+		(vm_fault_state_t *) current_thread()->ith_other;
+
+	(void) vm_fault(state->vmf_map,
+			state->vmf_vaddr,
+			state->vmf_fault_type,
+			state->vmf_change_wiring,
+			TRUE, state->vmf_continuation);
+	/*NOTREACHED*/
+}
+#endif /* CONTINUATIONS */
+
+kern_return_t vm_fault(map, vaddr, fault_type, change_wiring,
+		       resume, continuation)
+	vm_map_t	map;
+	vm_offset_t	vaddr;
+	vm_prot_t	fault_type;
+	boolean_t	change_wiring;
+	boolean_t	resume;
+	void		(*continuation)();
+{
+	vm_map_version_t	version;	/* Map version for verificiation */
+	boolean_t		wired;		/* Should mapping be wired down? */
+	vm_object_t		object;		/* Top-level object */
+	vm_offset_t		offset;		/* Top-level offset */
+	vm_prot_t		prot;		/* Protection for mapping */
+	vm_object_t		old_copy_object; /* Saved copy object */
+	vm_page_t		result_page;	/* Result of vm_fault_page */
+	vm_page_t		top_page;	/* Placeholder page */
+	kern_return_t		kr;
+
+	register
+	vm_page_t		m;	/* Fast access to result_page */
+
+#ifdef CONTINUATIONS
+	if (resume) {
+		register vm_fault_state_t *state =
+			(vm_fault_state_t *) current_thread()->ith_other;
+
+		/*
+		 *	Retrieve cached variables and
+		 *	continue vm_fault_page.
+		 */
+
+		object = state->vmf_object;
+		if (object == VM_OBJECT_NULL)
+			goto RetryFault;
+		version = state->vmf_version;
+		wired = state->vmf_wired;
+		offset = state->vmf_offset;
+		prot = state->vmf_prot;
+
+		kr = vm_fault_page(object, offset, fault_type,
+				(change_wiring && !wired), !change_wiring,
+				&prot, &result_page, &top_page,
+				TRUE, vm_fault_continue);
+		goto after_vm_fault_page;
+	}
+
+	if (continuation != (void (*)()) 0) {
+		/*
+		 *	We will probably need to save state.
+		 */
+
+		char *	state;
+
+		/*
+		 * if this assignment stmt is written as
+		 * 'active_threads[cpu_number()] = zalloc()',
+		 * cpu_number may be evaluated before zalloc;
+		 * if zalloc blocks, cpu_number will be wrong
+		 */
+
+		state = (char *) zalloc(vm_fault_state_zone);
+		current_thread()->ith_other = state;
+
+	}
+#else /* not CONTINUATIONS */
+	assert(continuation == 0);
+	assert(!resume);
+#endif /* not CONTINUATIONS */
+
+    RetryFault: ;
+
+	/*
+	 *	Find the backing store object and offset into
+	 *	it to begin the search.
+	 */
+
+	if ((kr = vm_map_lookup(&map, vaddr, fault_type, &version,
+				&object, &offset,
+				&prot, &wired)) != KERN_SUCCESS) {
+		goto done;
+	}
+
+	/*
+	 *	If the page is wired, we must fault for the current protection
+	 *	value, to avoid further faults.
+	 */
+
+	if (wired)
+		fault_type = prot;
+
+   	/*
+	 *	Make a reference to this object to
+	 *	prevent its disposal while we are messing with
+	 *	it.  Once we have the reference, the map is free
+	 *	to be diddled.  Since objects reference their
+	 *	shadows (and copies), they will stay around as well.
+	 */
+
+	assert(object->ref_count > 0);
+	object->ref_count++;
+	vm_object_paging_begin(object);
+
+#ifdef CONTINUATIONS
+	if (continuation != (void (*)()) 0) {
+		register vm_fault_state_t *state =
+			(vm_fault_state_t *) current_thread()->ith_other;
+
+		/*
+		 *	Save variables, in case vm_fault_page discards
+		 *	our kernel stack and we have to restart.
+		 */
+
+		state->vmf_map = map;
+		state->vmf_vaddr = vaddr;
+		state->vmf_fault_type = fault_type;
+		state->vmf_change_wiring = change_wiring;
+		state->vmf_continuation = continuation;
+
+		state->vmf_version = version;
+		state->vmf_wired = wired;
+		state->vmf_object = object;
+		state->vmf_offset = offset;
+		state->vmf_prot = prot;
+
+		kr = vm_fault_page(object, offset, fault_type,
+				   (change_wiring && !wired), !change_wiring,
+				   &prot, &result_page, &top_page,
+				   FALSE, vm_fault_continue);
+	} else
+#endif /* CONTINUATIONS */
+	{
+		kr = vm_fault_page(object, offset, fault_type,
+				   (change_wiring && !wired), !change_wiring,
+				   &prot, &result_page, &top_page,
+				   FALSE, (void (*)()) 0);
+	}
+    after_vm_fault_page:
+
+	/*
+	 *	If we didn't succeed, lose the object reference immediately.
+	 */
+
+	if (kr != VM_FAULT_SUCCESS)
+		vm_object_deallocate(object);
+
+	/*
+	 *	See why we failed, and take corrective action.
+	 */
+
+	switch (kr) {
+		case VM_FAULT_SUCCESS:
+			break;
+		case VM_FAULT_RETRY:
+			goto RetryFault;
+		case VM_FAULT_INTERRUPTED:
+			kr = KERN_SUCCESS;
+			goto done;
+		case VM_FAULT_MEMORY_SHORTAGE:
+#ifdef CONTINUATIONS
+			if (continuation != (void (*)()) 0) {
+				register vm_fault_state_t *state =
+					(vm_fault_state_t *) current_thread()->ith_other;
+
+				/*
+				 *	Save variables in case VM_PAGE_WAIT
+				 *	discards our kernel stack.
+				 */
+
+				state->vmf_map = map;
+				state->vmf_vaddr = vaddr;
+				state->vmf_fault_type = fault_type;
+				state->vmf_change_wiring = change_wiring;
+				state->vmf_continuation = continuation;
+				state->vmf_object = VM_OBJECT_NULL;
+
+				VM_PAGE_WAIT(vm_fault_continue);
+			} else
+#endif /* CONTINUATIONS */
+				VM_PAGE_WAIT((void (*)()) 0);
+			goto RetryFault;
+		case VM_FAULT_FICTITIOUS_SHORTAGE:
+			vm_page_more_fictitious();
+			goto RetryFault;
+		case VM_FAULT_MEMORY_ERROR:
+			kr = KERN_MEMORY_ERROR;
+			goto done;
+	}
+
+	m = result_page;
+
+	assert((change_wiring && !wired) ?
+	       (top_page == VM_PAGE_NULL) :
+	       ((top_page == VM_PAGE_NULL) == (m->object == object)));
+
+	/*
+	 *	How to clean up the result of vm_fault_page.  This
+	 *	happens whether the mapping is entered or not.
+	 */
+
+#define UNLOCK_AND_DEALLOCATE				\
+	MACRO_BEGIN					\
+	vm_fault_cleanup(m->object, top_page);		\
+	vm_object_deallocate(object);			\
+	MACRO_END
+
+	/*
+	 *	What to do with the resulting page from vm_fault_page
+	 *	if it doesn't get entered into the physical map:
+	 */
+
+#define RELEASE_PAGE(m)					\
+	MACRO_BEGIN					\
+	PAGE_WAKEUP_DONE(m);				\
+	vm_page_lock_queues();				\
+	if (!m->active && !m->inactive)			\
+		vm_page_activate(m);			\
+	vm_page_unlock_queues();			\
+	MACRO_END
+
+	/*
+	 *	We must verify that the maps have not changed
+	 *	since our last lookup.
+	 */
+
+	old_copy_object = m->object->copy;
+
+	vm_object_unlock(m->object);
+	while (!vm_map_verify(map, &version)) {
+		vm_object_t	retry_object;
+		vm_offset_t	retry_offset;
+		vm_prot_t	retry_prot;
+
+		/*
+		 *	To avoid trying to write_lock the map while another
+		 *	thread has it read_locked (in vm_map_pageable), we
+		 *	do not try for write permission.  If the page is
+		 *	still writable, we will get write permission.  If it
+		 *	is not, or has been marked needs_copy, we enter the
+		 *	mapping without write permission, and will merely
+		 *	take another fault.
+		 */
+		kr = vm_map_lookup(&map, vaddr,
+				   fault_type & ~VM_PROT_WRITE, &version,
+				   &retry_object, &retry_offset, &retry_prot,
+				   &wired);
+
+		if (kr != KERN_SUCCESS) {
+			vm_object_lock(m->object);
+			RELEASE_PAGE(m);
+			UNLOCK_AND_DEALLOCATE;
+			goto done;
+		}
+
+		vm_object_unlock(retry_object);
+		vm_object_lock(m->object);
+
+		if ((retry_object != object) ||
+		    (retry_offset != offset)) {
+			RELEASE_PAGE(m);
+			UNLOCK_AND_DEALLOCATE;
+			goto RetryFault;
+		}
+
+		/*
+		 *	Check whether the protection has changed or the object
+		 *	has been copied while we left the map unlocked.
+		 */
+		prot &= retry_prot;
+		vm_object_unlock(m->object);
+	}
+	vm_object_lock(m->object);
+
+	/*
+	 *	If the copy object changed while the top-level object
+	 *	was unlocked, then we must take away write permission.
+	 */
+
+	if (m->object->copy != old_copy_object)
+		prot &= ~VM_PROT_WRITE;
+
+	/*
+	 *	If we want to wire down this page, but no longer have
+	 *	adequate permissions, we must start all over.
+	 */
+
+	if (wired && (prot != fault_type)) {
+		vm_map_verify_done(map, &version);
+		RELEASE_PAGE(m);
+		UNLOCK_AND_DEALLOCATE;
+		goto RetryFault;
+	}
+
+	/*
+	 *	It's critically important that a wired-down page be faulted
+	 *	only once in each map for which it is wired.
+	 */
+
+	vm_object_unlock(m->object);
+
+	/*
+	 *	Put this page into the physical map.
+	 *	We had to do the unlock above because pmap_enter
+	 *	may cause other faults.  The page may be on
+	 *	the pageout queues.  If the pageout daemon comes
+	 *	across the page, it will remove it from the queues.
+	 */
+
+	PMAP_ENTER(map->pmap, vaddr, m, prot, wired);
+
+	/*
+	 *	If the page is not wired down and isn't already
+	 *	on a pageout queue, then put it where the
+	 *	pageout daemon can find it.
+	 */
+	vm_object_lock(m->object);
+	vm_page_lock_queues();
+	if (change_wiring) {
+		if (wired)
+			vm_page_wire(m);
+		else
+			vm_page_unwire(m);
+	} else if (software_reference_bits) {
+		if (!m->active && !m->inactive)
+			vm_page_activate(m);
+		m->reference = TRUE;
+	} else {
+		vm_page_activate(m);
+	}
+	vm_page_unlock_queues();
+
+	/*
+	 *	Unlock everything, and return
+	 */
+
+	vm_map_verify_done(map, &version);
+	PAGE_WAKEUP_DONE(m);
+	kr = KERN_SUCCESS;
+	UNLOCK_AND_DEALLOCATE;
+
+#undef	UNLOCK_AND_DEALLOCATE
+#undef	RELEASE_PAGE
+
+    done:
+#ifdef CONTINUATIONS
+	if (continuation != (void (*)()) 0) {
+		register vm_fault_state_t *state =
+			(vm_fault_state_t *) current_thread()->ith_other;
+
+		zfree(vm_fault_state_zone, (vm_offset_t) state);
+		(*continuation)(kr);
+		/*NOTREACHED*/
+	}
+#endif /* CONTINUATIONS */
+
+	return(kr);
+}
+
+kern_return_t	vm_fault_wire_fast();
+
+/*
+ *	vm_fault_wire:
+ *
+ *	Wire down a range of virtual addresses in a map.
+ */
+void vm_fault_wire(map, entry)
+	vm_map_t	map;
+	vm_map_entry_t	entry;
+{
+
+	register vm_offset_t	va;
+	register pmap_t		pmap;
+	register vm_offset_t	end_addr = entry->vme_end;
+
+	pmap = vm_map_pmap(map);
+
+	/*
+	 *	Inform the physical mapping system that the
+	 *	range of addresses may not fault, so that
+	 *	page tables and such can be locked down as well.
+	 */
+
+	pmap_pageable(pmap, entry->vme_start, end_addr, FALSE);
+
+	/*
+	 *	We simulate a fault to get the page and enter it
+	 *	in the physical map.
+	 */
+
+	for (va = entry->vme_start; va < end_addr; va += PAGE_SIZE) {
+		if (vm_fault_wire_fast(map, va, entry) != KERN_SUCCESS)
+			(void) vm_fault(map, va, VM_PROT_NONE, TRUE,
+					FALSE, (void (*)()) 0);
+	}
+}
+
+/*
+ *	vm_fault_unwire:
+ *
+ *	Unwire a range of virtual addresses in a map.
+ */
+void vm_fault_unwire(map, entry)
+	vm_map_t	map;
+	vm_map_entry_t	entry;
+{
+	register vm_offset_t	va;
+	register pmap_t		pmap;
+	register vm_offset_t	end_addr = entry->vme_end;
+	vm_object_t		object;
+
+	pmap = vm_map_pmap(map);
+
+	object = (entry->is_sub_map)
+			? VM_OBJECT_NULL : entry->object.vm_object;
+
+	/*
+	 *	Since the pages are wired down, we must be able to
+	 *	get their mappings from the physical map system.
+	 */
+
+	for (va = entry->vme_start; va < end_addr; va += PAGE_SIZE) {
+		pmap_change_wiring(pmap, va, FALSE);
+
+		if (object == VM_OBJECT_NULL) {
+			vm_map_lock_set_recursive(map);
+			(void) vm_fault(map, va, VM_PROT_NONE, TRUE,
+					FALSE, (void (*)()) 0);
+			vm_map_lock_clear_recursive(map);
+		} else {
+		 	vm_prot_t	prot;
+			vm_page_t	result_page;
+			vm_page_t	top_page;
+			vm_fault_return_t result;
+
+			do {
+				prot = VM_PROT_NONE;
+
+				vm_object_lock(object);
+				vm_object_paging_begin(object);
+			 	result = vm_fault_page(object,
+						entry->offset +
+						  (va - entry->vme_start),
+						VM_PROT_NONE, TRUE,
+						FALSE, &prot,
+						&result_page,
+						&top_page,
+						FALSE, (void (*)()) 0);
+			} while (result == VM_FAULT_RETRY);
+
+			if (result != VM_FAULT_SUCCESS)
+				panic("vm_fault_unwire: failure");
+
+			vm_page_lock_queues();
+			vm_page_unwire(result_page);
+			vm_page_unlock_queues();
+			PAGE_WAKEUP_DONE(result_page);
+
+			vm_fault_cleanup(result_page->object, top_page);
+		}
+	}
+
+	/*
+	 *	Inform the physical mapping system that the range
+	 *	of addresses may fault, so that page tables and
+	 *	such may be unwired themselves.
+	 */
+
+	pmap_pageable(pmap, entry->vme_start, end_addr, TRUE);
+}
+
+/*
+ *	vm_fault_wire_fast:
+ *
+ *	Handle common case of a wire down page fault at the given address.
+ *	If successful, the page is inserted into the associated physical map.
+ *	The map entry is passed in to avoid the overhead of a map lookup.
+ *
+ *	NOTE: the given address should be truncated to the
+ *	proper page address.
+ *
+ *	KERN_SUCCESS is returned if the page fault is handled; otherwise,
+ *	a standard error specifying why the fault is fatal is returned.
+ *
+ *	The map in question must be referenced, and remains so.
+ *	Caller has a read lock on the map.
+ *
+ *	This is a stripped version of vm_fault() for wiring pages.  Anything
+ *	other than the common case will return KERN_FAILURE, and the caller
+ *	is expected to call vm_fault().
+ */
+kern_return_t vm_fault_wire_fast(map, va, entry)
+	vm_map_t	map;
+	vm_offset_t	va;
+	vm_map_entry_t	entry;
+{
+	vm_object_t		object;
+	vm_offset_t		offset;
+	register vm_page_t	m;
+	vm_prot_t		prot;
+
+	vm_stat.faults++;		/* needs lock XXX */
+/*
+ *	Recovery actions
+ */
+
+#undef	RELEASE_PAGE
+#define RELEASE_PAGE(m)	{				\
+	PAGE_WAKEUP_DONE(m);				\
+	vm_page_lock_queues();				\
+	vm_page_unwire(m);				\
+	vm_page_unlock_queues();			\
+}
+
+
+#undef	UNLOCK_THINGS
+#define UNLOCK_THINGS	{				\
+	object->paging_in_progress--;			\
+	vm_object_unlock(object);			\
+}
+
+#undef	UNLOCK_AND_DEALLOCATE
+#define UNLOCK_AND_DEALLOCATE	{			\
+	UNLOCK_THINGS;					\
+	vm_object_deallocate(object);			\
+}
+/*
+ *	Give up and have caller do things the hard way.
+ */
+
+#define GIVE_UP {					\
+	UNLOCK_AND_DEALLOCATE;				\
+	return(KERN_FAILURE);				\
+}
+
+
+	/*
+	 *	If this entry is not directly to a vm_object, bail out.
+	 */
+	if (entry->is_sub_map)
+		return(KERN_FAILURE);
+
+	/*
+	 *	Find the backing store object and offset into it.
+	 */
+
+	object = entry->object.vm_object;
+	offset = (va - entry->vme_start) + entry->offset;
+	prot = entry->protection;
+
+   	/*
+	 *	Make a reference to this object to prevent its
+	 *	disposal while we are messing with it.
+	 */
+
+	vm_object_lock(object);
+	assert(object->ref_count > 0);
+	object->ref_count++;
+	object->paging_in_progress++;
+
+	/*
+	 *	INVARIANTS (through entire routine):
+	 *
+	 *	1)	At all times, we must either have the object
+	 *		lock or a busy page in some object to prevent
+	 *		some other thread from trying to bring in
+	 *		the same page.
+	 *
+	 *	2)	Once we have a busy page, we must remove it from
+	 *		the pageout queues, so that the pageout daemon
+	 *		will not grab it away.
+	 *
+	 */
+
+	/*
+	 *	Look for page in top-level object.  If it's not there or
+	 *	there's something going on, give up.
+	 */
+	m = vm_page_lookup(object, offset);
+	if ((m == VM_PAGE_NULL) || (m->error) ||
+	    (m->busy) || (m->absent) || (prot & m->page_lock)) {
+		GIVE_UP;
+	}
+
+	/*
+	 *	Wire the page down now.  All bail outs beyond this
+	 *	point must unwire the page.
+	 */
+
+	vm_page_lock_queues();
+	vm_page_wire(m);
+	vm_page_unlock_queues();
+
+	/*
+	 *	Mark page busy for other threads.
+	 */
+	assert(!m->busy);
+	m->busy = TRUE;
+	assert(!m->absent);
+
+	/*
+	 *	Give up if the page is being written and there's a copy object
+	 */
+	if ((object->copy != VM_OBJECT_NULL) && (prot & VM_PROT_WRITE)) {
+		RELEASE_PAGE(m);
+		GIVE_UP;
+	}
+
+	/*
+	 *	Put this page into the physical map.
+	 *	We have to unlock the object because pmap_enter
+	 *	may cause other faults.
+	 */
+	vm_object_unlock(object);
+
+	PMAP_ENTER(map->pmap, va, m, prot, TRUE);
+
+	/*
+	 *	Must relock object so that paging_in_progress can be cleared.
+	 */
+	vm_object_lock(object);
+
+	/*
+	 *	Unlock everything, and return
+	 */
+
+	PAGE_WAKEUP_DONE(m);
+	UNLOCK_AND_DEALLOCATE;
+
+	return(KERN_SUCCESS);
+
+}
+
+/*
+ *	Routine:	vm_fault_copy_cleanup
+ *	Purpose:
+ *		Release a page used by vm_fault_copy.
+ */
+
+void	vm_fault_copy_cleanup(page, top_page)
+	vm_page_t	page;
+	vm_page_t	top_page;
+{
+	vm_object_t	object = page->object;
+
+	vm_object_lock(object);
+	PAGE_WAKEUP_DONE(page);
+	vm_page_lock_queues();
+	if (!page->active && !page->inactive)
+		vm_page_activate(page);
+	vm_page_unlock_queues();
+	vm_fault_cleanup(object, top_page);
+}
+
+/*
+ *	Routine:	vm_fault_copy
+ *
+ *	Purpose:
+ *		Copy pages from one virtual memory object to another --
+ *		neither the source nor destination pages need be resident.
+ *
+ *		Before actually copying a page, the version associated with
+ *		the destination address map wil be verified.
+ *
+ *	In/out conditions:
+ *		The caller must hold a reference, but not a lock, to
+ *		each of the source and destination objects and to the
+ *		destination map.
+ *
+ *	Results:
+ *		Returns KERN_SUCCESS if no errors were encountered in
+ *		reading or writing the data.  Returns KERN_INTERRUPTED if
+ *		the operation was interrupted (only possible if the
+ *		"interruptible" argument is asserted).  Other return values
+ *		indicate a permanent error in copying the data.
+ *
+ *		The actual amount of data copied will be returned in the
+ *		"copy_size" argument.  In the event that the destination map
+ *		verification failed, this amount may be less than the amount
+ *		requested.
+ */
+kern_return_t	vm_fault_copy(
+			src_object,
+			src_offset,
+			src_size,
+			dst_object,
+			dst_offset,
+			dst_map,
+			dst_version,
+			interruptible
+			)
+	vm_object_t	src_object;
+	vm_offset_t	src_offset;
+	vm_size_t	*src_size;		/* INOUT */
+	vm_object_t	dst_object;
+	vm_offset_t	dst_offset;
+	vm_map_t	dst_map;
+	vm_map_version_t *dst_version;
+	boolean_t	interruptible;
+{
+	vm_page_t		result_page;
+	vm_prot_t		prot;
+
+	vm_page_t		src_page;
+	vm_page_t		src_top_page;
+
+	vm_page_t		dst_page;
+	vm_page_t		dst_top_page;
+
+	vm_size_t		amount_done;
+	vm_object_t		old_copy_object;
+
+#define	RETURN(x)					\
+	MACRO_BEGIN					\
+	*src_size = amount_done;			\
+	MACRO_RETURN(x);				\
+	MACRO_END
+
+	amount_done = 0;
+	do { /* while (amount_done != *src_size) */
+
+	    RetrySourceFault: ;
+
+		if (src_object == VM_OBJECT_NULL) {
+			/*
+			 *	No source object.  We will just
+			 *	zero-fill the page in dst_object.
+			 */
+
+			src_page = VM_PAGE_NULL;
+		} else {
+			prot = VM_PROT_READ;
+
+			vm_object_lock(src_object);
+			vm_object_paging_begin(src_object);
+
+			switch (vm_fault_page(src_object, src_offset,
+					VM_PROT_READ, FALSE, interruptible,
+					&prot, &result_page, &src_top_page,
+					FALSE, (void (*)()) 0)) {
+
+				case VM_FAULT_SUCCESS:
+					break;
+				case VM_FAULT_RETRY:
+					goto RetrySourceFault;
+				case VM_FAULT_INTERRUPTED:
+					RETURN(MACH_SEND_INTERRUPTED);
+				case VM_FAULT_MEMORY_SHORTAGE:
+					VM_PAGE_WAIT((void (*)()) 0);
+					goto RetrySourceFault;
+				case VM_FAULT_FICTITIOUS_SHORTAGE:
+					vm_page_more_fictitious();
+					goto RetrySourceFault;
+				case VM_FAULT_MEMORY_ERROR:
+					return(KERN_MEMORY_ERROR);
+			}
+
+			src_page = result_page;
+
+			assert((src_top_page == VM_PAGE_NULL) ==
+					(src_page->object == src_object));
+
+			assert ((prot & VM_PROT_READ) != VM_PROT_NONE);
+
+			vm_object_unlock(src_page->object);
+		}
+
+	    RetryDestinationFault: ;
+
+		prot = VM_PROT_WRITE;
+
+		vm_object_lock(dst_object);
+		vm_object_paging_begin(dst_object);
+
+		switch (vm_fault_page(dst_object, dst_offset, VM_PROT_WRITE,
+				FALSE, FALSE /* interruptible */,
+				&prot, &result_page, &dst_top_page,
+				FALSE, (void (*)()) 0)) {
+
+			case VM_FAULT_SUCCESS:
+				break;
+			case VM_FAULT_RETRY:
+				goto RetryDestinationFault;
+			case VM_FAULT_INTERRUPTED:
+				if (src_page != VM_PAGE_NULL)
+					vm_fault_copy_cleanup(src_page,
+							      src_top_page);
+				RETURN(MACH_SEND_INTERRUPTED);
+			case VM_FAULT_MEMORY_SHORTAGE:
+				VM_PAGE_WAIT((void (*)()) 0);
+				goto RetryDestinationFault;
+			case VM_FAULT_FICTITIOUS_SHORTAGE:
+				vm_page_more_fictitious();
+				goto RetryDestinationFault;
+			case VM_FAULT_MEMORY_ERROR:
+				if (src_page != VM_PAGE_NULL)
+					vm_fault_copy_cleanup(src_page,
+							      src_top_page);
+				return(KERN_MEMORY_ERROR);
+		}
+		assert ((prot & VM_PROT_WRITE) != VM_PROT_NONE);
+
+		dst_page = result_page;
+
+		old_copy_object = dst_page->object->copy;
+
+		vm_object_unlock(dst_page->object);
+
+		if (!vm_map_verify(dst_map, dst_version)) {
+
+		 BailOut: ;
+
+			if (src_page != VM_PAGE_NULL)
+				vm_fault_copy_cleanup(src_page, src_top_page);
+			vm_fault_copy_cleanup(dst_page, dst_top_page);
+			break;
+		}
+
+
+		vm_object_lock(dst_page->object);
+		if (dst_page->object->copy != old_copy_object) {
+			vm_object_unlock(dst_page->object);
+			vm_map_verify_done(dst_map, dst_version);
+			goto BailOut;
+		}
+		vm_object_unlock(dst_page->object);
+
+		/*
+		 *	Copy the page, and note that it is dirty
+		 *	immediately.
+		 */
+
+		if (src_page == VM_PAGE_NULL)
+			vm_page_zero_fill(dst_page);
+		else
+			vm_page_copy(src_page, dst_page);
+		dst_page->dirty = TRUE;
+
+		/*
+		 *	Unlock everything, and return
+		 */
+
+		vm_map_verify_done(dst_map, dst_version);
+
+		if (src_page != VM_PAGE_NULL)
+			vm_fault_copy_cleanup(src_page, src_top_page);
+		vm_fault_copy_cleanup(dst_page, dst_top_page);
+
+		amount_done += PAGE_SIZE;
+		src_offset += PAGE_SIZE;
+		dst_offset += PAGE_SIZE;
+
+	} while (amount_done != *src_size);
+
+	RETURN(KERN_SUCCESS);
+#undef	RETURN
+
+	/*NOTREACHED*/
+}
+
+
+
+
+
+#ifdef	notdef
+
+/*
+ *	Routine:	vm_fault_page_overwrite
+ *
+ *	Description:
+ *		A form of vm_fault_page that assumes that the
+ *		resulting page will be overwritten in its entirety,
+ *		making it unnecessary to obtain the correct *contents*
+ *		of the page.
+ *
+ *	Implementation:
+ *		XXX Untested.  Also unused.  Eventually, this technology
+ *		could be used in vm_fault_copy() to advantage.
+ */
+vm_fault_return_t vm_fault_page_overwrite(dst_object, dst_offset, result_page)
+	register
+	vm_object_t	dst_object;
+	vm_offset_t	dst_offset;
+	vm_page_t	*result_page;	/* OUT */
+{
+	register
+	vm_page_t	dst_page;
+
+#define	interruptible	FALSE	/* XXX */
+
+	while (TRUE) {
+		/*
+		 *	Look for a page at this offset
+		 */
+
+		while ((dst_page = vm_page_lookup(dst_object, dst_offset))
+				 == VM_PAGE_NULL) {
+			/*
+			 *	No page, no problem... just allocate one.
+			 */
+
+			dst_page = vm_page_alloc(dst_object, dst_offset);
+			if (dst_page == VM_PAGE_NULL) {
+				vm_object_unlock(dst_object);
+				VM_PAGE_WAIT((void (*)()) 0);
+				vm_object_lock(dst_object);
+				continue;
+			}
+
+			/*
+			 *	Pretend that the memory manager
+			 *	write-protected the page.
+			 *
+			 *	Note that we will be asking for write
+			 *	permission without asking for the data
+			 *	first.
+			 */
+
+			dst_page->overwriting = TRUE;
+			dst_page->page_lock = VM_PROT_WRITE;
+			dst_page->absent = TRUE;
+			dst_object->absent_count++;
+
+			break;
+
+			/*
+			 *	When we bail out, we might have to throw
+			 *	away the page created here.
+			 */
+
+#define	DISCARD_PAGE						\
+	MACRO_BEGIN						\
+	vm_object_lock(dst_object);				\
+	dst_page = vm_page_lookup(dst_object, dst_offset);	\
+	if ((dst_page != VM_PAGE_NULL) && dst_page->overwriting) \
+	   	VM_PAGE_FREE(dst_page);				\
+	vm_object_unlock(dst_object);				\
+	MACRO_END
+		}
+
+		/*
+		 *	If the page is write-protected...
+		 */
+
+		if (dst_page->page_lock & VM_PROT_WRITE) {
+			/*
+			 *	... and an unlock request hasn't been sent
+			 */
+
+			if ( ! (dst_page->unlock_request & VM_PROT_WRITE)) {
+				vm_prot_t	u;
+				kern_return_t	rc;
+
+				/*
+				 *	... then send one now.
+				 */
+
+				if (!dst_object->pager_ready) {
+					vm_object_assert_wait(dst_object,
+						VM_OBJECT_EVENT_PAGER_READY,
+						interruptible);
+					vm_object_unlock(dst_object);
+					thread_block((void (*)()) 0);
+					if (current_thread()->wait_result !=
+					    THREAD_AWAKENED) {
+						DISCARD_PAGE;
+						return(VM_FAULT_INTERRUPTED);
+					}
+					continue;
+				}
+
+				u = dst_page->unlock_request |= VM_PROT_WRITE;
+				vm_object_unlock(dst_object);
+
+				if ((rc = memory_object_data_unlock(
+						dst_object->pager,
+						dst_object->pager_request,
+						dst_offset + dst_object->paging_offset,
+						PAGE_SIZE,
+						u)) != KERN_SUCCESS) {
+				     	printf("vm_object_overwrite: memory_object_data_unlock failed\n");
+					DISCARD_PAGE;
+					return((rc == MACH_SEND_INTERRUPTED) ?
+						VM_FAULT_INTERRUPTED :
+						VM_FAULT_MEMORY_ERROR);
+				}
+				vm_object_lock(dst_object);
+				continue;
+			}
+
+			/* ... fall through to wait below */
+		} else {
+			/*
+			 *	If the page isn't being used for other
+			 *	purposes, then we're done.
+			 */
+			if ( ! (dst_page->busy || dst_page->absent || dst_page->error) )
+				break;
+		}
+
+		PAGE_ASSERT_WAIT(dst_page, interruptible);
+		vm_object_unlock(dst_object);
+		thread_block((void (*)()) 0);
+		if (current_thread()->wait_result != THREAD_AWAKENED) {
+			DISCARD_PAGE;
+			return(VM_FAULT_INTERRUPTED);
+		}
+	}
+
+	*result_page = dst_page;
+	return(VM_FAULT_SUCCESS);
+
+#undef	interruptible
+#undef	DISCARD_PAGE
+}
+
+#endif	/* notdef */
diff -Npur gnumach.old/vm/vm_pageout.c gnumach.new/vm/vm_pageout.c
--- gnumach.old/vm/vm_pageout.c	2006-03-20 08:31:36.000000000 -0300
+++ gnumach.new/vm/vm_pageout.c	2006-04-05 23:37:11.000000000 -0300
@@ -677,18 +677,8 @@ void vm_pageout_scan()
 			thread_will_wait_with_timeout(current_thread(), msecs);
 			counter(c_vm_pageout_scan_block++);
 			thread_block(vm_pageout_scan_continue);
-#ifndef CONTINUATIONS
-			/*
-			 *	Unfortunately, we don't have call_continuation
-			 *	so we can't rely on tail-recursion.
-			 */
-
-			vm_pageout_scan_continue();
-			goto Restart;
-#else	/* CONTINUATIONS */
 			call_continuation(vm_pageout_scan_continue);
 			/*NOTREACHED*/
-#endif	/* CONTINUATIONS */
 		}
 
 		vm_pageout_inactive++;
@@ -887,10 +877,8 @@ void vm_pageout_scan_continue()
 	}
 	vm_page_unlock_queues();
 
-#ifdef	CONTINUATIONS
 	vm_pageout_continue();
 	/*NOTREACHED*/
-#endif	/* CONTINUATIONS */
 }
 
 /*
diff -Npur gnumach.old/vm/vm_pageout.c.~1.7.2.1.~ gnumach.new/vm/vm_pageout.c.~1.7.2.1.~
--- gnumach.old/vm/vm_pageout.c.~1.7.2.1.~	1969-12-31 21:00:00.000000000 -0300
+++ gnumach.new/vm/vm_pageout.c.~1.7.2.1.~	2006-03-20 08:31:36.000000000 -0300
@@ -0,0 +1,986 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
+ * Copyright (c) 1993,1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL).
+ * 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, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
+ * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
+ * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
+ * THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ *	File:	vm/vm_pageout.c
+ *	Author:	Avadis Tevanian, Jr., Michael Wayne Young
+ *	Date:	1985
+ *
+ *	The proverbial page-out daemon.
+ */
+
+#include <mach_pagemap.h>
+
+#include <mach/mach_types.h>
+#include <mach/memory_object.h>
+#include "memory_object_default.h"
+#include "memory_object_user.h"
+#include <mach/vm_param.h>
+#include <mach/vm_statistics.h>
+#include <kern/counters.h>
+#include <kern/thread.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+#include <machine/vm_tuning.h>
+
+
+
+#ifndef	VM_PAGEOUT_BURST_MAX
+#define	VM_PAGEOUT_BURST_MAX	10		/* number of pages */
+#endif	/* VM_PAGEOUT_BURST_MAX */
+
+#ifndef	VM_PAGEOUT_BURST_MIN
+#define	VM_PAGEOUT_BURST_MIN	5		/* number of pages */
+#endif	/* VM_PAGEOUT_BURST_MIN */
+
+#ifndef	VM_PAGEOUT_BURST_WAIT
+#define	VM_PAGEOUT_BURST_WAIT	10		/* milliseconds per page */
+#endif	/* VM_PAGEOUT_BURST_WAIT */
+
+#ifndef	VM_PAGEOUT_EMPTY_WAIT
+#define VM_PAGEOUT_EMPTY_WAIT	75		/* milliseconds */
+#endif	/* VM_PAGEOUT_EMPTY_WAIT */
+
+#ifndef	VM_PAGEOUT_PAUSE_MAX
+#define	VM_PAGEOUT_PAUSE_MAX	10		/* number of pauses */
+#endif	/* VM_PAGEOUT_PAUSE_MAX */
+
+/*
+ *	To obtain a reasonable LRU approximation, the inactive queue
+ *	needs to be large enough to give pages on it a chance to be
+ *	referenced a second time.  This macro defines the fraction
+ *	of active+inactive pages that should be inactive.
+ *	The pageout daemon uses it to update vm_page_inactive_target.
+ *
+ *	If vm_page_free_count falls below vm_page_free_target and
+ *	vm_page_inactive_count is below vm_page_inactive_target,
+ *	then the pageout daemon starts running.
+ */
+
+#ifndef	VM_PAGE_INACTIVE_TARGET
+#define	VM_PAGE_INACTIVE_TARGET(avail)	((avail) * 2 / 3)
+#endif	/* VM_PAGE_INACTIVE_TARGET */
+
+/*
+ *	Once the pageout daemon starts running, it keeps going
+ *	until vm_page_free_count meets or exceeds vm_page_free_target.
+ */
+
+#ifndef	VM_PAGE_FREE_TARGET
+#define	VM_PAGE_FREE_TARGET(free)	(15 + (free) / 80)
+#endif	/* VM_PAGE_FREE_TARGET */
+
+/*
+ *	The pageout daemon always starts running once vm_page_free_count
+ *	falls below vm_page_free_min.
+ */
+
+#ifndef	VM_PAGE_FREE_MIN
+#define	VM_PAGE_FREE_MIN(free)	(10 + (free) / 100)
+#endif	/* VM_PAGE_FREE_MIN */
+
+/*      When vm_page_external_count exceeds vm_page_external_limit, 
+ *	allocations of externally paged pages stops.
+ */
+
+#ifndef VM_PAGE_EXTERNAL_LIMIT
+#define VM_PAGE_EXTERNAL_LIMIT(free)		((free) / 2)
+#endif  /* VM_PAGE_EXTERNAL_LIMIT */
+
+/*	Attempt to keep the number of externally paged pages less
+ *	than vm_pages_external_target.
+ */
+#ifndef VM_PAGE_EXTERNAL_TARGET
+#define VM_PAGE_EXTERNAL_TARGET(free)		((free) / 4)
+#endif  /* VM_PAGE_EXTERNAL_TARGET */
+
+/*
+ *	When vm_page_free_count falls below vm_page_free_reserved,
+ *	only vm-privileged threads can allocate pages.  vm-privilege
+ *	allows the pageout daemon and default pager (and any other
+ *	associated threads needed for default pageout) to continue
+ *	operation by dipping into the reserved pool of pages.  */
+
+#ifndef	VM_PAGE_FREE_RESERVED
+#define	VM_PAGE_FREE_RESERVED			50
+#endif	/* VM_PAGE_FREE_RESERVED */
+
+/*
+ *	When vm_page_free_count falls below vm_pageout_reserved_internal,
+ *	the pageout daemon no longer trusts external pagers to clean pages.
+ *	External pagers are probably all wedged waiting for a free page.
+ *	It forcibly double-pages dirty pages belonging to external objects,
+ *	getting the pages to the default pager to clean.
+ */
+
+#ifndef	VM_PAGEOUT_RESERVED_INTERNAL
+#define	VM_PAGEOUT_RESERVED_INTERNAL(reserve)	((reserve) - 25)
+#endif	/* VM_PAGEOUT_RESERVED_INTERNAL */
+
+/*
+ *	When vm_page_free_count falls below vm_pageout_reserved_really,
+ *	the pageout daemon stops work entirely to let the default pager
+ *	catch up (assuming the default pager has pages to clean).
+ *	Beyond this point, it is too dangerous to consume memory
+ *	even for memory_object_data_write messages to the default pager.
+ */
+
+#ifndef	VM_PAGEOUT_RESERVED_REALLY
+#define	VM_PAGEOUT_RESERVED_REALLY(reserve)	((reserve) - 40)
+#endif	/* VM_PAGEOUT_RESERVED_REALLY */
+
+extern void vm_pageout_continue();
+extern void vm_pageout_scan_continue();
+
+unsigned int vm_pageout_reserved_internal = 0;
+unsigned int vm_pageout_reserved_really = 0;
+
+unsigned int vm_page_external_target = 0;
+
+unsigned int vm_pageout_burst_max = 0;
+unsigned int vm_pageout_burst_min = 0;
+unsigned int vm_pageout_burst_wait = 0;		/* milliseconds per page */
+unsigned int vm_pageout_empty_wait = 0;		/* milliseconds */
+unsigned int vm_pageout_pause_count = 0;
+unsigned int vm_pageout_pause_max = 0;
+
+/*
+ *	These variables record the pageout daemon's actions:
+ *	how many pages it looks at and what happens to those pages.
+ *	No locking needed because only one thread modifies the variables.
+ */
+
+unsigned int vm_pageout_active = 0;		/* debugging */
+unsigned int vm_pageout_inactive = 0;		/* debugging */
+unsigned int vm_pageout_inactive_nolock = 0;	/* debugging */
+unsigned int vm_pageout_inactive_busy = 0;	/* debugging */
+unsigned int vm_pageout_inactive_absent = 0;	/* debugging */
+unsigned int vm_pageout_inactive_used = 0;	/* debugging */
+unsigned int vm_pageout_inactive_clean = 0;	/* debugging */
+unsigned int vm_pageout_inactive_dirty = 0;	/* debugging */
+unsigned int vm_pageout_inactive_double = 0;	/* debugging */
+unsigned int vm_pageout_inactive_cleaned_external = 0;
+
+/*
+ *	Routine:	vm_pageout_setup
+ *	Purpose:
+ *		Set up a page for pageout.
+ *
+ *		Move or copy the page to a new object, as part
+ *		of which it will be sent to its memory manager
+ *		in a memory_object_data_write or memory_object_initialize
+ *		message.
+ *
+ *		The "paging_offset" argument specifies the offset
+ *		of the page within its external memory object.
+ *
+ *		The "new_object" and "new_offset" arguments
+ *		indicate where the page should be moved.
+ *
+ *		The "flush" argument specifies whether the page
+ *		should be flushed from its object.  If not, a
+ *		copy of the page is moved to the new object.
+ *
+ *	In/Out conditions:
+ *		The page in question must not be on any pageout queues,
+ *		and must be busy.  The object to which it belongs
+ *		must be unlocked, and the caller must hold a paging
+ *		reference to it.  The new_object must not be locked.
+ *
+ *		If the page is flushed from its original object,
+ *		this routine returns a pointer to a place-holder page,
+ *		inserted at the same offset, to block out-of-order
+ *		requests for the page.  The place-holder page must
+ *		be freed after the data_write or initialize message
+ *		has been sent.  If the page is copied,
+ *		the holding page is VM_PAGE_NULL.
+ *
+ *		The original page is put on a paging queue and marked
+ *		not busy on exit.
+ */
+vm_page_t
+vm_pageout_setup(m, paging_offset, new_object, new_offset, flush)
+	register vm_page_t	m;
+	vm_offset_t		paging_offset;
+	register vm_object_t	new_object;
+	vm_offset_t		new_offset;
+	boolean_t		flush;
+{
+	register vm_object_t	old_object = m->object;
+	register vm_page_t	holding_page = 0; /*'=0'to quiet gcc warnings*/
+	register vm_page_t	new_m;
+
+	assert(m->busy && !m->absent && !m->fictitious);
+
+	/*
+	 *	If we are not flushing the page, allocate a
+	 *	page in the object.  If we cannot get the
+	 *	page, flush instead.
+	 */
+	if (!flush) {
+		vm_object_lock(new_object);
+		new_m = vm_page_alloc(new_object, new_offset);
+		if (new_m == VM_PAGE_NULL)
+			flush = TRUE;
+		vm_object_unlock(new_object);
+	}
+
+	if (flush) {
+		/*
+		 *	Create a place-holder page where the old one was,
+		 *	to prevent anyone from attempting to page in this
+		 *	page while we`re unlocked.
+		 */
+		while ((holding_page = vm_page_grab_fictitious())
+							== VM_PAGE_NULL)
+			vm_page_more_fictitious();
+
+		vm_object_lock(old_object);
+		vm_page_lock_queues();
+		vm_page_remove(m);
+		vm_page_unlock_queues();
+		PAGE_WAKEUP_DONE(m);
+
+		vm_page_lock_queues();
+		vm_page_insert(holding_page, old_object, m->offset);
+		vm_page_unlock_queues();
+
+		/*
+		 *	Record that this page has been written out
+		 */
+#if	MACH_PAGEMAP
+		vm_external_state_set(old_object->existence_info,
+					paging_offset,
+					VM_EXTERNAL_STATE_EXISTS);
+#endif	/* MACH_PAGEMAP */
+
+		vm_object_unlock(old_object);
+
+		vm_object_lock(new_object);
+
+		/*
+		 *	Move this page into the new object
+		 */
+
+		vm_page_lock_queues();
+		vm_page_insert(m, new_object, new_offset);
+		vm_page_unlock_queues();
+
+		m->dirty = TRUE;
+		m->precious = FALSE;
+		m->page_lock = VM_PROT_NONE;
+		m->unlock_request = VM_PROT_NONE;
+	}
+	else {
+		/*
+		 *	Copy the data into the new page,
+		 *	and mark the new page as clean.
+		 */
+		vm_page_copy(m, new_m);
+
+		vm_object_lock(old_object);
+		m->dirty = FALSE;
+		pmap_clear_modify(m->phys_addr);
+
+		/*
+		 *	Deactivate old page.
+		 */
+		vm_page_lock_queues();
+		vm_page_deactivate(m);
+		vm_page_unlock_queues();
+
+		PAGE_WAKEUP_DONE(m);
+
+		/*
+		 *	Record that this page has been written out
+		 */
+
+#if	MACH_PAGEMAP
+		vm_external_state_set(old_object->existence_info,
+					paging_offset,
+					VM_EXTERNAL_STATE_EXISTS);
+#endif	/* MACH_PAGEMAP */
+
+		vm_object_unlock(old_object);
+
+		vm_object_lock(new_object);
+
+		/*
+		 *	Use the new page below.
+		 */
+		m = new_m;
+		m->dirty = TRUE;
+		assert(!m->precious);
+		PAGE_WAKEUP_DONE(m);
+	}
+
+	/*
+	 *	Make the old page eligible for replacement again; if a
+	 *	user-supplied memory manager fails to release the page,
+	 *	it will be paged out again to the default memory manager.
+	 *
+	 *	Note that pages written to the default memory manager
+	 *	must be wired down -- in return, it guarantees to free
+	 *	this page, rather than reusing it.
+	 */
+
+	vm_page_lock_queues();
+	vm_stat.pageouts++;
+	if (m->laundry) {
+		/*
+		 *	vm_pageout_scan is telling us to put this page
+		 *	at the front of the inactive queue, so it will
+		 *	be immediately paged out to the default pager.
+		 */
+
+		assert(!old_object->internal);
+		m->laundry = FALSE;
+
+		queue_enter_first(&vm_page_queue_inactive, m,
+				  vm_page_t, pageq);
+		m->inactive = TRUE;
+		vm_page_inactive_count++;
+	} else if (old_object->internal) {
+		m->laundry = TRUE;
+		vm_page_laundry_count++;
+
+		vm_page_wire(m);
+	} else
+		vm_page_activate(m);
+	vm_page_unlock_queues();
+
+	/*
+	 *	Since IPC operations may block, we drop locks now.
+	 *	[The placeholder page is busy, and we still have
+	 *	paging_in_progress incremented.]
+	 */
+
+	vm_object_unlock(new_object);
+
+	/*
+	 *	Return the placeholder page to simplify cleanup.
+	 */
+	return (flush ? holding_page : VM_PAGE_NULL);
+}
+
+/*
+ *	Routine:	vm_pageout_page
+ *	Purpose:
+ *		Causes the specified page to be written back to
+ *		the appropriate memory object.
+ *
+ *		The "initial" argument specifies whether this
+ *		data is an initialization only, and should use
+ *		memory_object_data_initialize instead of
+ *		memory_object_data_write.
+ *
+ *		The "flush" argument specifies whether the page
+ *		should be flushed from the object.  If not, a
+ *		copy of the data is sent to the memory object.
+ *
+ *	In/out conditions:
+ *		The page in question must not be on any pageout queues.
+ *		The object to which it belongs must be locked.
+ *	Implementation:
+ *		Move this page to a completely new object, if flushing;
+ *		copy to a new page in a new object, if not.
+ */
+void
+vm_pageout_page(m, initial, flush)
+	register vm_page_t	m;
+	boolean_t		initial;
+	boolean_t		flush;
+{
+	vm_map_copy_t		copy;
+	register vm_object_t	old_object;
+	register vm_object_t	new_object;
+	register vm_page_t	holding_page;
+	vm_offset_t		paging_offset;
+	kern_return_t		rc;
+	boolean_t		precious_clean;
+
+	assert(m->busy);
+
+	/*
+	 *	Cleaning but not flushing a clean precious page is a
+	 *	no-op.  Remember whether page is clean and precious now
+	 *	because vm_pageout_setup will mark it dirty and not precious.
+	 *
+	 * XXX Check if precious_clean && !flush can really happen.
+	 */
+	precious_clean = (!m->dirty) && m->precious;
+	if (precious_clean && !flush) {
+		PAGE_WAKEUP_DONE(m);
+		return;
+	}
+
+	/*
+	 *	Verify that we really want to clean this page.
+	 */
+	if (m->absent || m->error || (!m->dirty && !m->precious)) {
+		VM_PAGE_FREE(m);
+		return;
+	}
+
+	/*
+	 *	Create a paging reference to let us play with the object.
+	 */
+	old_object = m->object;
+	paging_offset = m->offset + old_object->paging_offset;
+	vm_object_paging_begin(old_object);
+	vm_object_unlock(old_object);
+
+	/*
+	 *	Allocate a new object into which we can put the page.
+	 */
+	new_object = vm_object_allocate(PAGE_SIZE);
+
+	/*
+	 *	Move the page into the new object.
+	 */
+	holding_page = vm_pageout_setup(m,
+				paging_offset,
+				new_object,
+				0,		/* new offset */
+				flush);		/* flush */
+
+	rc = vm_map_copyin_object(new_object, 0, PAGE_SIZE, &copy);
+	assert(rc == KERN_SUCCESS);
+
+	if (initial || old_object->use_old_pageout) {
+		rc = (*(initial ? memory_object_data_initialize
+			     : memory_object_data_write))
+			(old_object->pager,
+			 old_object->pager_request,
+			 paging_offset, (pointer_t) copy, PAGE_SIZE);
+	}
+	else {
+		rc = memory_object_data_return(
+			 old_object->pager,
+			 old_object->pager_request,
+			 paging_offset, (pointer_t) copy, PAGE_SIZE,
+			 !precious_clean, !flush);
+	}
+
+	if (rc != KERN_SUCCESS)
+		vm_map_copy_discard(copy);
+
+	/*
+	 *	Clean up.
+	 */
+	vm_object_lock(old_object);
+	if (holding_page != VM_PAGE_NULL)
+	    VM_PAGE_FREE(holding_page);
+	vm_object_paging_end(old_object);
+}
+
+/*
+ *	vm_pageout_scan does the dirty work for the pageout daemon.
+ *	It returns with vm_page_queue_free_lock held and
+ *	vm_page_free_wanted == 0.
+ */
+
+void vm_pageout_scan()
+{
+	unsigned int burst_count;
+	unsigned int want_pages;
+
+	/*
+	 *	We want to gradually dribble pages from the active queue
+	 *	to the inactive queue.  If we let the inactive queue get
+	 *	very small, and then suddenly dump many pages into it,
+	 *	those pages won't get a sufficient chance to be referenced
+	 *	before we start taking them from the inactive queue.
+	 *
+	 *	We must limit the rate at which we send pages to the pagers.
+	 *	data_write messages consume memory, for message buffers and
+	 *	for map-copy objects.  If we get too far ahead of the pagers,
+	 *	we can potentially run out of memory.
+	 *
+	 *	We can use the laundry count to limit directly the number
+	 *	of pages outstanding to the default pager.  A similar
+	 *	strategy for external pagers doesn't work, because
+	 *	external pagers don't have to deallocate the pages sent them,
+	 *	and because we might have to send pages to external pagers
+	 *	even if they aren't processing writes.  So we also
+	 *	use a burst count to limit writes to external pagers.
+	 *
+	 *	When memory is very tight, we can't rely on external pagers to
+	 *	clean pages.  They probably aren't running, because they
+	 *	aren't vm-privileged.  If we kept sending dirty pages to them,
+	 *	we could exhaust the free list.  However, we can't just ignore
+	 *	pages belonging to external objects, because there might be no
+	 *	pages belonging to internal objects.  Hence, we get the page
+	 *	into an internal object and then immediately double-page it,
+	 *	sending it to the default pager.
+	 *
+	 *	consider_zone_gc should be last, because the other operations
+	 *	might return memory to zones.  When we pause we use
+	 *	vm_pageout_scan_continue as our continuation, so we will
+	 *	reenter vm_pageout_scan periodically and attempt to reclaim
+	 *	internal memory even if we never reach vm_page_free_target.
+	 */
+
+    Restart:
+	stack_collect();
+	net_kmsg_collect();
+	consider_task_collect();
+	consider_thread_collect();
+	consider_zone_gc();
+
+	for (burst_count = 0;;) {
+		register vm_page_t m;
+		register vm_object_t object;
+		unsigned int free_count;
+
+		/*
+		 *	Recalculate vm_page_inactivate_target.
+		 */
+
+		vm_page_lock_queues();
+		vm_page_inactive_target =
+			VM_PAGE_INACTIVE_TARGET(vm_page_active_count +
+						vm_page_inactive_count);
+
+		/*
+		 *	Move pages from active to inactive.
+		 */
+
+		while ((vm_page_inactive_count < vm_page_inactive_target) &&
+		       !queue_empty(&vm_page_queue_active)) {
+			register vm_object_t obj;
+
+			vm_pageout_active++;
+			m = (vm_page_t) queue_first(&vm_page_queue_active);
+			assert(m->active && !m->inactive);
+
+			obj = m->object;
+			if (!vm_object_lock_try(obj)) {
+				/*
+				 *	Move page to end and continue.
+				 */
+
+				queue_remove(&vm_page_queue_active, m,
+					     vm_page_t, pageq);
+				queue_enter(&vm_page_queue_active, m,
+					    vm_page_t, pageq);
+				vm_page_unlock_queues();
+				vm_page_lock_queues();
+				continue;
+			}
+
+			/*
+			 *	If the page is busy, then we pull it
+			 *	off the active queue and leave it alone.
+			 */
+
+			if (m->busy) {
+				vm_object_unlock(obj);
+				queue_remove(&vm_page_queue_active, m,
+					     vm_page_t, pageq);
+				m->active = FALSE;
+				vm_page_active_count--;
+				continue;
+			}
+
+			/*
+			 *	Deactivate the page while holding the object
+			 *	locked, so we know the page is still not busy.
+			 *	This should prevent races between pmap_enter
+			 *	and pmap_clear_reference.  The page might be
+			 *	absent or fictitious, but vm_page_deactivate
+			 *	can handle that.
+			 */
+
+			vm_page_deactivate(m);
+			vm_object_unlock(obj);
+		}
+
+		/*
+		 *	We are done if we have met our targets *and*
+		 *	nobody is still waiting for a page.
+		 */
+
+		simple_lock(&vm_page_queue_free_lock);
+		free_count = vm_page_free_count;
+		if ((free_count >= vm_page_free_target) &&
+		    (vm_page_external_count <= vm_page_external_target) &&
+		    (vm_page_free_wanted == 0)) {
+			vm_page_unlock_queues();
+			break;
+		}
+		want_pages = ((free_count < vm_page_free_target) ||
+			      vm_page_free_wanted);
+		simple_unlock(&vm_page_queue_free_lock);
+
+		/*
+		 * Sometimes we have to pause:
+		 *	1) No inactive pages - nothing to do.
+		 *	2) Flow control - wait for pagers to catch up.
+		 *	3) Extremely low memory - sending out dirty pages
+		 *	consumes memory.  We don't take the risk of doing
+		 *	this if the default pager already has work to do.
+		 */
+	pause:
+		if (queue_empty(&vm_page_queue_inactive) ||
+		    (burst_count >= vm_pageout_burst_max) ||
+		    (vm_page_laundry_count >= vm_pageout_burst_max) ||
+		    ((free_count < vm_pageout_reserved_really) &&
+		     (vm_page_laundry_count > 0))) {
+			unsigned int pages, msecs;
+
+			/*
+			 *	vm_pageout_burst_wait is msecs/page.
+			 *	If there is nothing for us to do, we wait
+			 *	at least vm_pageout_empty_wait msecs.
+			 */
+
+			if (vm_page_laundry_count > burst_count)
+				pages = vm_page_laundry_count;
+			else
+				pages = burst_count;
+			msecs = pages * vm_pageout_burst_wait;
+
+			if (queue_empty(&vm_page_queue_inactive) &&
+			    (msecs < vm_pageout_empty_wait))
+				msecs = vm_pageout_empty_wait;
+			vm_page_unlock_queues();
+
+			thread_will_wait_with_timeout(current_thread(), msecs);
+			counter(c_vm_pageout_scan_block++);
+			thread_block(vm_pageout_scan_continue);
+#ifndef CONTINUATIONS
+			/*
+			 *	Unfortunately, we don't have call_continuation
+			 *	so we can't rely on tail-recursion.
+			 */
+
+			vm_pageout_scan_continue();
+			goto Restart;
+#else	/* CONTINUATIONS */
+			call_continuation(vm_pageout_scan_continue);
+			/*NOTREACHED*/
+#endif	/* CONTINUATIONS */
+		}
+
+		vm_pageout_inactive++;
+
+		/* Find a page we are interested in paging out.  If we
+		   need pages, then we'll page anything out; otherwise
+		   we only page out external pages. */
+		m = (vm_page_t) queue_first (&vm_page_queue_inactive);
+		while (1)
+		  {
+		    assert (!m->active && m->inactive);
+		    if (want_pages || m->external)
+		      break;
+		    
+		    m = (vm_page_t) queue_next (m);
+		    if (!m)
+		      goto pause;
+		  }
+		
+		object = m->object;
+
+		/*
+		 *	Try to lock object; since we've got the
+		 *	page queues lock, we can only try for this one.
+		 */
+
+		if (!vm_object_lock_try(object)) {
+			/*
+			 *	Move page to end and continue.
+			 */
+
+			queue_remove(&vm_page_queue_inactive, m,
+				     vm_page_t, pageq);
+			queue_enter(&vm_page_queue_inactive, m,
+				    vm_page_t, pageq);
+			vm_page_unlock_queues();
+			vm_pageout_inactive_nolock++;
+			continue;
+		}
+
+		/*
+		 *	Remove the page from the inactive list.
+		 */
+
+		queue_remove(&vm_page_queue_inactive, m, vm_page_t, pageq);
+		vm_page_inactive_count--;
+		m->inactive = FALSE;
+
+		if (m->busy || !object->alive) {
+			/*
+			 *	Somebody is already playing with this page.
+			 *	Leave it off the pageout queues.
+			 */
+
+			vm_page_unlock_queues();
+			vm_object_unlock(object);
+			vm_pageout_inactive_busy++;
+			continue;
+		}
+
+		/*
+		 *	If it's absent, we can reclaim the page.
+		 */
+
+		if (want_pages && m->absent) {
+			vm_pageout_inactive_absent++;
+		    reclaim_page:
+			vm_page_free(m);
+			vm_page_unlock_queues();
+			vm_object_unlock(object);
+			continue;
+		}
+
+		/*
+		 *	If it's being used, reactivate.
+		 *	(Fictitious pages are either busy or absent.)
+		 */
+
+		assert(!m->fictitious);
+		if (m->reference || pmap_is_referenced(m->phys_addr)) {
+			vm_object_unlock(object);
+			vm_page_activate(m);
+			vm_stat.reactivations++;
+			vm_page_unlock_queues();
+			vm_pageout_inactive_used++;
+			continue;
+		}
+
+		/*
+		 *	Eliminate all mappings.
+		 */
+
+		m->busy = TRUE;
+		pmap_page_protect(m->phys_addr, VM_PROT_NONE);
+		if (!m->dirty)
+			m->dirty = pmap_is_modified(m->phys_addr);
+
+		if (m->external) {
+			/* Figure out if we still care about this
+			page in the limit of externally managed pages.
+			Clean pages don't actually cause system hosage,
+			so it's ok to stop considering them as
+			"consumers" of memory. */
+			if (m->dirty && !m->extcounted) {
+				m->extcounted = TRUE;
+				vm_page_external_count++;
+			} else if (!m->dirty && m->extcounted) {
+				m->extcounted = FALSE;
+				vm_page_external_count--;
+			}
+		}
+		
+		/* If we don't actually need more memory, and the page
+		   is not dirty, put it on the tail of the inactive queue
+		   and move on to the next page. */
+		if (!want_pages && !m->dirty) {
+			queue_remove (&vm_page_queue_inactive, m, 
+				      vm_page_t, pageq);
+			queue_enter (&vm_page_queue_inactive, m,
+				     vm_page_t, pageq);
+			vm_page_unlock_queues();
+			vm_pageout_inactive_cleaned_external++;
+			continue;
+		}			
+
+		/*
+		 *	If it's clean and not precious, we can free the page.
+		 */
+
+		if (!m->dirty && !m->precious) {
+			vm_pageout_inactive_clean++;
+			goto reclaim_page;
+		}
+
+		/*
+		 *	If we are very low on memory, then we can't
+		 *	rely on an external pager to clean a dirty page,
+		 *	because external pagers are not vm-privileged.
+		 *
+		 *	The laundry bit tells vm_pageout_setup to
+		 *	put the page back at the front of the inactive
+		 *	queue instead of activating the page.  Hence,
+		 *	we will pick the page up again immediately and
+		 *	resend it to the default pager.
+		 */
+
+		assert(!m->laundry);
+		if ((free_count < vm_pageout_reserved_internal) &&
+		    !object->internal) {
+			m->laundry = TRUE;
+			vm_pageout_inactive_double++;
+		}
+		vm_page_unlock_queues();
+
+		/*
+		 *	If there is no memory object for the page, create
+		 *	one and hand it to the default pager.
+		 *	[First try to collapse, so we don't create
+		 *	one unnecessarily.]
+		 */
+
+		if (!object->pager_initialized)
+			vm_object_collapse(object);
+		if (!object->pager_initialized)
+			vm_object_pager_create(object);
+		if (!object->pager_initialized)
+			panic("vm_pageout_scan");
+
+		vm_pageout_inactive_dirty++;
+		vm_pageout_page(m, FALSE, TRUE);	/* flush it */
+		vm_object_unlock(object);
+		burst_count++;
+	}
+}
+
+void vm_pageout_scan_continue()
+{
+	/*
+	 *	We just paused to let the pagers catch up.
+	 *	If vm_page_laundry_count is still high,
+	 *	then we aren't waiting long enough.
+	 *	If we have paused some vm_pageout_pause_max times without
+	 *	adjusting vm_pageout_burst_wait, it might be too big,
+	 *	so we decrease it.
+	 */
+
+	vm_page_lock_queues();
+	if (vm_page_laundry_count > vm_pageout_burst_min) {
+		vm_pageout_burst_wait++;
+		vm_pageout_pause_count = 0;
+	} else if (++vm_pageout_pause_count > vm_pageout_pause_max) {
+		vm_pageout_burst_wait = (vm_pageout_burst_wait * 3) / 4;
+		if (vm_pageout_burst_wait < 1)
+			vm_pageout_burst_wait = 1;
+		vm_pageout_pause_count = 0;
+	}
+	vm_page_unlock_queues();
+
+#ifdef	CONTINUATIONS
+	vm_pageout_continue();
+	/*NOTREACHED*/
+#endif	/* CONTINUATIONS */
+}
+
+/*
+ *	vm_pageout is the high level pageout daemon.
+ */
+
+void vm_pageout_continue()
+{
+	/*
+	 *	The pageout daemon is never done, so loop forever.
+	 *	We should call vm_pageout_scan at least once each
+	 *	time we are woken, even if vm_page_free_wanted is
+	 *	zero, to check vm_page_free_target and
+	 *	vm_page_inactive_target.
+	 */
+
+	for (;;) {
+		vm_pageout_scan();
+		/* we hold vm_page_queue_free_lock now */
+		assert(vm_page_free_wanted == 0);
+
+		assert_wait(&vm_page_free_wanted, FALSE);
+		simple_unlock(&vm_page_queue_free_lock);
+		counter(c_vm_pageout_block++);
+		thread_block(vm_pageout_continue);
+	}
+}
+
+void vm_pageout()
+{
+	int		free_after_reserve;
+
+	current_thread()->vm_privilege = TRUE;
+	stack_privilege(current_thread());
+
+	/*
+	 *	Initialize some paging parameters.
+	 */
+
+	if (vm_pageout_burst_max == 0)
+		vm_pageout_burst_max = VM_PAGEOUT_BURST_MAX;
+
+	if (vm_pageout_burst_min == 0)
+		vm_pageout_burst_min = VM_PAGEOUT_BURST_MIN;
+
+	if (vm_pageout_burst_wait == 0)
+		vm_pageout_burst_wait = VM_PAGEOUT_BURST_WAIT;
+
+	if (vm_pageout_empty_wait == 0)
+		vm_pageout_empty_wait = VM_PAGEOUT_EMPTY_WAIT;
+
+	if (vm_page_free_reserved == 0)
+		vm_page_free_reserved = VM_PAGE_FREE_RESERVED;
+
+	if (vm_pageout_pause_max == 0)
+		vm_pageout_pause_max = VM_PAGEOUT_PAUSE_MAX;
+
+	if (vm_pageout_reserved_internal == 0)
+		vm_pageout_reserved_internal =
+			VM_PAGEOUT_RESERVED_INTERNAL(vm_page_free_reserved);
+
+	if (vm_pageout_reserved_really == 0)
+		vm_pageout_reserved_really =
+			VM_PAGEOUT_RESERVED_REALLY(vm_page_free_reserved);
+
+	free_after_reserve = vm_page_free_count - vm_page_free_reserved;
+
+	if (vm_page_external_limit == 0)
+	        vm_page_external_limit = 
+			VM_PAGE_EXTERNAL_LIMIT (free_after_reserve);
+
+	if (vm_page_external_target == 0)
+	        vm_page_external_target = 
+			VM_PAGE_EXTERNAL_TARGET (free_after_reserve);
+
+	if (vm_page_free_min == 0)
+		vm_page_free_min = vm_page_free_reserved +
+			VM_PAGE_FREE_MIN(free_after_reserve);
+
+	if (vm_page_free_target == 0)
+		vm_page_free_target = vm_page_free_reserved +
+			VM_PAGE_FREE_TARGET(free_after_reserve);
+
+	if (vm_page_free_target < vm_page_free_min + 5)
+		vm_page_free_target = vm_page_free_min + 5;
+
+	/*
+	 *	vm_pageout_scan will set vm_page_inactive_target.
+	 */
+
+	vm_pageout_continue();
+	/*NOTREACHED*/
+}
diff -Npur gnumach.old/vm/vm_resident.c gnumach.new/vm/vm_resident.c
--- gnumach.old/vm/vm_resident.c	2006-01-31 06:21:05.000000000 -0300
+++ gnumach.new/vm/vm_resident.c	2006-04-05 23:37:49.000000000 -0300
@@ -1200,10 +1200,6 @@ void vm_page_wait(
 	void (*continuation)(void))
 {
 
-#ifndef CONTINUATIONS
-	assert (continuation == 0);
-#endif
-
 	/*
 	 *	We can't use vm_page_free_reserved to make this
 	 *	determination.  Consider: some thread might
diff -Npur gnumach.old/vm/vm_resident.c.~1.7.4.1.~ gnumach.new/vm/vm_resident.c.~1.7.4.1.~
--- gnumach.old/vm/vm_resident.c.~1.7.4.1.~	1969-12-31 21:00:00.000000000 -0300
+++ gnumach.new/vm/vm_resident.c.~1.7.4.1.~	2006-01-31 06:21:05.000000000 -0300
@@ -0,0 +1,1526 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
+ * Copyright (c) 1993,1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL).
+ * 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, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
+ * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
+ * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
+ * THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ *	File:	vm/vm_page.c
+ *	Author:	Avadis Tevanian, Jr., Michael Wayne Young
+ *
+ *	Resident memory management module.
+ */
+#include <cpus.h>
+
+#include <mach/vm_prot.h>
+#include <kern/counters.h>
+#include <kern/sched_prim.h>
+#include <kern/task.h>
+#include <kern/thread.h>
+#include <mach/vm_statistics.h>
+#include <machine/vm_param.h>
+#include <kern/xpr.h>
+#include <kern/zalloc.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_kern.h>
+
+#include <mach_vm_debug.h>
+#if	MACH_VM_DEBUG
+#include <mach/kern_return.h>
+#include <mach_debug/hash_info.h>
+#include <vm/vm_user.h>
+#endif
+
+/* in zalloc.c XXX */
+extern vm_offset_t	zdata;
+extern vm_size_t	zdata_size;
+
+/*
+ *	Associated with eacn page of user-allocatable memory is a
+ *	page structure.
+ */
+
+/*
+ *	These variables record the values returned by vm_page_bootstrap,
+ *	for debugging purposes.  The implementation of pmap_steal_memory
+ *	and pmap_startup here also uses them internally.
+ */
+
+vm_offset_t virtual_space_start;
+vm_offset_t virtual_space_end;
+
+/*
+ *	The vm_page_lookup() routine, which provides for fast
+ *	(virtual memory object, offset) to page lookup, employs
+ *	the following hash table.  The vm_page_{insert,remove}
+ *	routines install and remove associations in the table.
+ *	[This table is often called the virtual-to-physical,
+ *	or VP, table.]
+ */
+typedef struct {
+	decl_simple_lock_data(,lock)
+	vm_page_t pages;
+} vm_page_bucket_t;
+
+vm_page_bucket_t *vm_page_buckets;		/* Array of buckets */
+unsigned int	vm_page_bucket_count = 0;	/* How big is array? */
+unsigned int	vm_page_hash_mask;		/* Mask for hash function */
+
+/*
+ *	Resident page structures are initialized from
+ *	a template (see vm_page_alloc).
+ *
+ *	When adding a new field to the virtual memory
+ *	object structure, be sure to add initialization
+ *	(see vm_page_bootstrap).
+ */
+struct vm_page	vm_page_template;
+
+/*
+ *	Resident pages that represent real memory
+ *	are allocated from a free list.
+ */
+vm_page_t	vm_page_queue_free;
+vm_page_t	vm_page_queue_fictitious;
+decl_simple_lock_data(,vm_page_queue_free_lock)
+unsigned int	vm_page_free_wanted;
+int		vm_page_free_count;
+int		vm_page_fictitious_count;
+int		vm_page_external_count;
+
+unsigned int	vm_page_free_count_minimum;	/* debugging */
+
+/*
+ *	Occasionally, the virtual memory system uses
+ *	resident page structures that do not refer to
+ *	real pages, for example to leave a page with
+ *	important state information in the VP table.
+ *
+ *	These page structures are allocated the way
+ *	most other kernel structures are.
+ */
+zone_t	vm_page_zone;
+
+/*
+ *	Fictitious pages don't have a physical address,
+ *	but we must initialize phys_addr to something.
+ *	For debugging, this should be a strange value
+ *	that the pmap module can recognize in assertions.
+ */
+vm_offset_t vm_page_fictitious_addr = (vm_offset_t) -1;
+
+/*
+ *	Resident page structures are also chained on
+ *	queues that are used by the page replacement
+ *	system (pageout daemon).  These queues are
+ *	defined here, but are shared by the pageout
+ *	module.
+ */
+queue_head_t	vm_page_queue_active;
+queue_head_t	vm_page_queue_inactive;
+decl_simple_lock_data(,vm_page_queue_lock)
+int	vm_page_active_count;
+int	vm_page_inactive_count;
+int	vm_page_wire_count;
+
+/*
+ *	Several page replacement parameters are also
+ *	shared with this module, so that page allocation
+ *	(done here in vm_page_alloc) can trigger the
+ *	pageout daemon.
+ */
+int	vm_page_free_target = 0;
+int	vm_page_free_min = 0;
+int	vm_page_inactive_target = 0;
+int	vm_page_free_reserved = 0;
+int	vm_page_laundry_count = 0;
+int	vm_page_external_limit = 0;
+
+
+/*
+ *	The VM system has a couple of heuristics for deciding
+ *	that pages are "uninteresting" and should be placed
+ *	on the inactive queue as likely candidates for replacement.
+ *	These variables let the heuristics be controlled at run-time
+ *	to make experimentation easier.
+ */
+
+boolean_t vm_page_deactivate_behind = TRUE;
+boolean_t vm_page_deactivate_hint = TRUE;
+
+/*
+ *	vm_page_bootstrap:
+ *
+ *	Initializes the resident memory module.
+ *
+ *	Allocates memory for the page cells, and
+ *	for the object/offset-to-page hash table headers.
+ *	Each page cell is initialized and placed on the free list.
+ *	Returns the range of available kernel virtual memory.
+ */
+
+void vm_page_bootstrap(
+	vm_offset_t *startp,
+	vm_offset_t *endp)
+{
+	register vm_page_t m;
+	int i;
+
+	/*
+	 *	Initialize the vm_page template.
+	 */
+
+	m = &vm_page_template;
+	m->object = VM_OBJECT_NULL;	/* reset later */
+	m->offset = 0;			/* reset later */
+	m->wire_count = 0;
+
+	m->inactive = FALSE;
+	m->active = FALSE;
+	m->laundry = FALSE;
+	m->free = FALSE;
+	m->external = FALSE;
+
+	m->busy = TRUE;
+	m->wanted = FALSE;
+	m->tabled = FALSE;
+	m->fictitious = FALSE;
+	m->private = FALSE;
+	m->absent = FALSE;
+	m->error = FALSE;
+	m->dirty = FALSE;
+	m->precious = FALSE;
+	m->reference = FALSE;
+
+	m->phys_addr = 0;		/* reset later */
+
+	m->page_lock = VM_PROT_NONE;
+	m->unlock_request = VM_PROT_NONE;
+
+	/*
+	 *	Initialize the page queues.
+	 */
+
+	simple_lock_init(&vm_page_queue_free_lock);
+	simple_lock_init(&vm_page_queue_lock);
+
+	vm_page_queue_free = VM_PAGE_NULL;
+	vm_page_queue_fictitious = VM_PAGE_NULL;
+	queue_init(&vm_page_queue_active);
+	queue_init(&vm_page_queue_inactive);
+
+	vm_page_free_wanted = 0;
+
+	/*
+	 *	Steal memory for the zone system.
+	 */
+
+	kentry_data_size = kentry_count * sizeof(struct vm_map_entry);
+	kentry_data = pmap_steal_memory(kentry_data_size);
+
+	zdata = pmap_steal_memory(zdata_size);
+
+	/*
+	 *	Allocate (and initialize) the virtual-to-physical
+	 *	table hash buckets.
+	 *
+	 *	The number of buckets should be a power of two to
+	 *	get a good hash function.  The following computation
+	 *	chooses the first power of two that is greater
+	 *	than the number of physical pages in the system.
+	 */
+
+	if (vm_page_bucket_count == 0) {
+		unsigned int npages = pmap_free_pages();
+
+		vm_page_bucket_count = 1;
+		while (vm_page_bucket_count < npages)
+			vm_page_bucket_count <<= 1;
+	}
+
+	vm_page_hash_mask = vm_page_bucket_count - 1;
+
+	if (vm_page_hash_mask & vm_page_bucket_count)
+		printf("vm_page_bootstrap: WARNING -- strange page hash\n");
+
+	vm_page_buckets = (vm_page_bucket_t *)
+		pmap_steal_memory(vm_page_bucket_count *
+				  sizeof(vm_page_bucket_t));
+
+	for (i = 0; i < vm_page_bucket_count; i++) {
+		register vm_page_bucket_t *bucket = &vm_page_buckets[i];
+
+		bucket->pages = VM_PAGE_NULL;
+		simple_lock_init(&bucket->lock);
+	}
+
+	/*
+	 *	Machine-dependent code allocates the resident page table.
+	 *	It uses vm_page_init to initialize the page frames.
+	 *	The code also returns to us the virtual space available
+	 *	to the kernel.  We don't trust the pmap module
+	 *	to get the alignment right.
+	 */
+
+	pmap_startup(&virtual_space_start, &virtual_space_end);
+	virtual_space_start = round_page(virtual_space_start);
+	virtual_space_end = trunc_page(virtual_space_end);
+
+	*startp = virtual_space_start;
+	*endp = virtual_space_end;
+
+	/*	printf("vm_page_bootstrap: %d free pages\n", vm_page_free_count);*/
+	vm_page_free_count_minimum = vm_page_free_count;
+}
+
+#ifndef	MACHINE_PAGES
+/*
+ *	We implement pmap_steal_memory and pmap_startup with the help
+ *	of two simpler functions, pmap_virtual_space and pmap_next_page.
+ */
+
+vm_offset_t pmap_steal_memory(
+	vm_size_t size)
+{
+	vm_offset_t addr, vaddr, paddr;
+
+	/*
+	 *	We round the size to an integer multiple.
+	 */
+
+	size = (size + 3) &~ 3;
+
+	/*
+	 *	If this is the first call to pmap_steal_memory,
+	 *	we have to initialize ourself.
+	 */
+
+	if (virtual_space_start == virtual_space_end) {
+		pmap_virtual_space(&virtual_space_start, &virtual_space_end);
+
+		/*
+		 *	The initial values must be aligned properly, and
+		 *	we don't trust the pmap module to do it right.
+		 */
+
+		virtual_space_start = round_page(virtual_space_start);
+		virtual_space_end = trunc_page(virtual_space_end);
+	}
+
+	/*
+	 *	Allocate virtual memory for this request.
+	 */
+
+	addr = virtual_space_start;
+	virtual_space_start += size;
+
+	/*
+	 *	Allocate and map physical pages to back new virtual pages.
+	 */
+
+	for (vaddr = round_page(addr);
+	     vaddr < addr + size;
+	     vaddr += PAGE_SIZE) {
+		if (!pmap_next_page(&paddr))
+			panic("pmap_steal_memory");
+
+		/*
+		 *	XXX Logically, these mappings should be wired,
+		 *	but some pmap modules barf if they are.
+		 */
+
+		pmap_enter(kernel_pmap, vaddr, paddr,
+			   VM_PROT_READ|VM_PROT_WRITE, FALSE);
+	}
+
+	return addr;
+}
+
+void pmap_startup(
+	vm_offset_t *startp,
+	vm_offset_t *endp)
+{
+	unsigned int i, npages, pages_initialized;
+	vm_page_t pages;
+	vm_offset_t paddr;
+
+	/*
+	 *	We calculate how many page frames we will have
+	 *	and then allocate the page structures in one chunk.
+	 */
+
+	npages = ((PAGE_SIZE * pmap_free_pages() +
+		   (round_page(virtual_space_start) - virtual_space_start)) /
+		  (PAGE_SIZE + sizeof *pages));
+
+	pages = (vm_page_t) pmap_steal_memory(npages * sizeof *pages);
+
+	/*
+	 *	Initialize the page frames.
+	 */
+
+	for (i = 0, pages_initialized = 0; i < npages; i++) {
+		if (!pmap_next_page(&paddr))
+			break;
+
+		vm_page_init(&pages[i], paddr);
+		pages_initialized++;
+	}
+
+	/*
+	 * Release pages in reverse order so that physical pages
+	 * initially get allocated in ascending addresses. This keeps
+	 * the devices (which must address physical memory) happy if
+	 * they require several consecutive pages.
+	 */
+
+	for (i = pages_initialized; i > 0; i--) {
+		vm_page_release(&pages[i - 1], FALSE);
+	}
+
+	/*
+	 *	We have to re-align virtual_space_start,
+	 *	because pmap_steal_memory has been using it.
+	 */
+
+	virtual_space_start = round_page(virtual_space_start);
+
+	*startp = virtual_space_start;
+	*endp = virtual_space_end;
+}
+#endif	/* MACHINE_PAGES */
+
+/*
+ *	Routine:	vm_page_module_init
+ *	Purpose:
+ *		Second initialization pass, to be done after
+ *		the basic VM system is ready.
+ */
+void		vm_page_module_init(void)
+{
+	vm_page_zone = zinit((vm_size_t) sizeof(struct vm_page),
+			     VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS,
+			     PAGE_SIZE,
+			     0, "vm pages");
+}
+
+/*
+ *	Routine:	vm_page_create
+ *	Purpose:
+ *		After the VM system is up, machine-dependent code
+ *		may stumble across more physical memory.  For example,
+ *		memory that it was reserving for a frame buffer.
+ *		vm_page_create turns this memory into available pages.
+ */
+
+void vm_page_create(
+	vm_offset_t	start,
+	vm_offset_t	end)
+{
+	vm_offset_t paddr;
+	vm_page_t m;
+
+	for (paddr = round_page(start);
+	     paddr < trunc_page(end);
+	     paddr += PAGE_SIZE) {
+		m = (vm_page_t) zalloc(vm_page_zone);
+		if (m == VM_PAGE_NULL)
+			panic("vm_page_create");
+
+		vm_page_init(m, paddr);
+		vm_page_release(m, FALSE);
+	}
+}
+
+/*
+ *	vm_page_hash:
+ *
+ *	Distributes the object/offset key pair among hash buckets.
+ *
+ *	NOTE:	To get a good hash function, the bucket count should
+ *		be a power of two.
+ */
+#define vm_page_hash(object, offset) \
+	(((unsigned int)(vm_offset_t)object + (unsigned int)atop(offset)) \
+		& vm_page_hash_mask)
+
+/*
+ *	vm_page_insert:		[ internal use only ]
+ *
+ *	Inserts the given mem entry into the object/object-page
+ *	table and object list.
+ *
+ *	The object and page must be locked.
+ */
+
+void vm_page_insert(
+	register vm_page_t	mem,
+	register vm_object_t	object,
+	register vm_offset_t	offset)
+{
+	register vm_page_bucket_t *bucket;
+
+	VM_PAGE_CHECK(mem);
+
+	if (mem->tabled)
+		panic("vm_page_insert");
+
+	/*
+	 *	Record the object/offset pair in this page
+	 */
+
+	mem->object = object;
+	mem->offset = offset;
+
+	/*
+	 *	Insert it into the object_object/offset hash table
+	 */
+
+	bucket = &vm_page_buckets[vm_page_hash(object, offset)];
+	simple_lock(&bucket->lock);
+	mem->next = bucket->pages;
+	bucket->pages = mem;
+	simple_unlock(&bucket->lock);
+
+	/*
+	 *	Now link into the object's list of backed pages.
+	 */
+
+	queue_enter(&object->memq, mem, vm_page_t, listq);
+	mem->tabled = TRUE;
+
+	/*
+	 *	Show that the object has one more resident page.
+	 */
+
+	object->resident_page_count++;
+
+	/*
+	 *	Detect sequential access and inactivate previous page.
+	 *	We ignore busy pages.
+	 */
+
+	if (vm_page_deactivate_behind &&
+	    (offset == object->last_alloc + PAGE_SIZE)) {
+		vm_page_t	last_mem;
+
+		last_mem = vm_page_lookup(object, object->last_alloc);
+		if ((last_mem != VM_PAGE_NULL) && !last_mem->busy)
+			vm_page_deactivate(last_mem);
+	}
+	object->last_alloc = offset;
+}
+
+/*
+ *	vm_page_replace:
+ *
+ *	Exactly like vm_page_insert, except that we first
+ *	remove any existing page at the given offset in object
+ *	and we don't do deactivate-behind.
+ *
+ *	The object and page must be locked.
+ */
+
+void vm_page_replace(
+	register vm_page_t	mem,
+	register vm_object_t	object,
+	register vm_offset_t	offset)
+{
+	register vm_page_bucket_t *bucket;
+
+	VM_PAGE_CHECK(mem);
+
+	if (mem->tabled)
+		panic("vm_page_replace");
+
+	/*
+	 *	Record the object/offset pair in this page
+	 */
+
+	mem->object = object;
+	mem->offset = offset;
+
+	/*
+	 *	Insert it into the object_object/offset hash table,
+	 *	replacing any page that might have been there.
+	 */
+
+	bucket = &vm_page_buckets[vm_page_hash(object, offset)];
+	simple_lock(&bucket->lock);
+	if (bucket->pages) {
+		vm_page_t *mp = &bucket->pages;
+		register vm_page_t m = *mp;
+		do {
+			if (m->object == object && m->offset == offset) {
+				/*
+				 * Remove page from bucket and from object,
+				 * and return it to the free list.
+				 */
+				*mp = m->next;
+				queue_remove(&object->memq, m, vm_page_t,
+					     listq);
+				m->tabled = FALSE;
+				object->resident_page_count--;
+
+				/*
+				 * Return page to the free list.
+				 * Note the page is not tabled now, so this
+				 * won't self-deadlock on the bucket lock.
+				 */
+
+				vm_page_free(m);
+				break;
+			}
+			mp = &m->next;
+		} while ((m = *mp) != 0);
+		mem->next = bucket->pages;
+	} else {
+		mem->next = VM_PAGE_NULL;
+	}
+	bucket->pages = mem;
+	simple_unlock(&bucket->lock);
+
+	/*
+	 *	Now link into the object's list of backed pages.
+	 */
+
+	queue_enter(&object->memq, mem, vm_page_t, listq);
+	mem->tabled = TRUE;
+
+	/*
+	 *	And show that the object has one more resident
+	 *	page.
+	 */
+
+	object->resident_page_count++;
+}
+
+/*
+ *	vm_page_remove:		[ internal use only ]
+ *
+ *	Removes the given mem entry from the object/offset-page
+ *	table and the object page list.
+ *
+ *	The object and page must be locked.
+ */
+
+void vm_page_remove(
+	register vm_page_t	mem)
+{
+	register vm_page_bucket_t	*bucket;
+	register vm_page_t	this;
+
+	assert(mem->tabled);
+	VM_PAGE_CHECK(mem);
+
+	/*
+	 *	Remove from the object_object/offset hash table
+	 */
+
+	bucket = &vm_page_buckets[vm_page_hash(mem->object, mem->offset)];
+	simple_lock(&bucket->lock);
+	if ((this = bucket->pages) == mem) {
+		/* optimize for common case */
+
+		bucket->pages = mem->next;
+	} else {
+		register vm_page_t	*prev;
+
+		for (prev = &this->next;
+		     (this = *prev) != mem;
+		     prev = &this->next)
+			continue;
+		*prev = this->next;
+	}
+	simple_unlock(&bucket->lock);
+
+	/*
+	 *	Now remove from the object's list of backed pages.
+	 */
+
+	queue_remove(&mem->object->memq, mem, vm_page_t, listq);
+
+	/*
+	 *	And show that the object has one fewer resident
+	 *	page.
+	 */
+
+	mem->object->resident_page_count--;
+
+	mem->tabled = FALSE;
+}
+
+/*
+ *	vm_page_lookup:
+ *
+ *	Returns the page associated with the object/offset
+ *	pair specified; if none is found, VM_PAGE_NULL is returned.
+ *
+ *	The object must be locked.  No side effects.
+ */
+
+vm_page_t vm_page_lookup(
+	register vm_object_t	object,
+	register vm_offset_t	offset)
+{
+	register vm_page_t	mem;
+	register vm_page_bucket_t *bucket;
+
+	/*
+	 *	Search the hash table for this object/offset pair
+	 */
+
+	bucket = &vm_page_buckets[vm_page_hash(object, offset)];
+
+	simple_lock(&bucket->lock);
+	for (mem = bucket->pages; mem != VM_PAGE_NULL; mem = mem->next) {
+		VM_PAGE_CHECK(mem);
+		if ((mem->object == object) && (mem->offset == offset))
+			break;
+	}
+	simple_unlock(&bucket->lock);
+	return mem;
+}
+
+/*
+ *	vm_page_rename:
+ *
+ *	Move the given memory entry from its
+ *	current object to the specified target object/offset.
+ *
+ *	The object must be locked.
+ */
+void vm_page_rename(
+	register vm_page_t	mem,
+	register vm_object_t	new_object,
+	vm_offset_t		new_offset)
+{
+	/*
+	 *	Changes to mem->object require the page lock because
+	 *	the pageout daemon uses that lock to get the object.
+	 */
+
+	vm_page_lock_queues();
+    	vm_page_remove(mem);
+	vm_page_insert(mem, new_object, new_offset);
+	vm_page_unlock_queues();
+}
+
+/*
+ *	vm_page_init:
+ *
+ *	Initialize the fields in a new page.
+ *	This takes a structure with random values and initializes it
+ *	so that it can be given to vm_page_release or vm_page_insert.
+ */
+void vm_page_init(
+	vm_page_t	mem,
+	vm_offset_t	phys_addr)
+{
+	*mem = vm_page_template;
+	mem->phys_addr = phys_addr;
+}
+
+/*
+ *	vm_page_grab_fictitious:
+ *
+ *	Remove a fictitious page from the free list.
+ *	Returns VM_PAGE_NULL if there are no free pages.
+ */
+
+vm_page_t vm_page_grab_fictitious(void)
+{
+	register vm_page_t m;
+
+	simple_lock(&vm_page_queue_free_lock);
+	m = vm_page_queue_fictitious;
+	if (m != VM_PAGE_NULL) {
+		vm_page_fictitious_count--;
+		vm_page_queue_fictitious = (vm_page_t) m->pageq.next;
+		m->free = FALSE;
+	}
+	simple_unlock(&vm_page_queue_free_lock);
+
+	return m;
+}
+
+/*
+ *	vm_page_release_fictitious:
+ *
+ *	Release a fictitious page to the free list.
+ */
+
+void vm_page_release_fictitious(
+	register vm_page_t m)
+{
+	simple_lock(&vm_page_queue_free_lock);
+	if (m->free)
+		panic("vm_page_release_fictitious");
+	m->free = TRUE;
+	m->pageq.next = (queue_entry_t) vm_page_queue_fictitious;
+	vm_page_queue_fictitious = m;
+	vm_page_fictitious_count++;
+	simple_unlock(&vm_page_queue_free_lock);
+}
+
+/*
+ *	vm_page_more_fictitious:
+ *
+ *	Add more fictitious pages to the free list.
+ *	Allowed to block.
+ */
+
+int vm_page_fictitious_quantum = 5;
+
+void vm_page_more_fictitious(void)
+{
+	register vm_page_t m;
+	int i;
+
+	for (i = 0; i < vm_page_fictitious_quantum; i++) {
+		m = (vm_page_t) zalloc(vm_page_zone);
+		if (m == VM_PAGE_NULL)
+			panic("vm_page_more_fictitious");
+
+		vm_page_init(m, vm_page_fictitious_addr);
+		m->fictitious = TRUE;
+		vm_page_release_fictitious(m);
+	}
+}
+
+/*
+ *	vm_page_convert:
+ *
+ *	Attempt to convert a fictitious page into a real page.
+ */
+
+boolean_t vm_page_convert(
+	register vm_page_t m,
+	boolean_t external)
+{
+	register vm_page_t real_m;
+
+	real_m = vm_page_grab(external);
+	if (real_m == VM_PAGE_NULL)
+		return FALSE;
+
+	m->phys_addr = real_m->phys_addr;
+	m->fictitious = FALSE;
+
+	real_m->phys_addr = vm_page_fictitious_addr;
+	real_m->fictitious = TRUE;
+
+	vm_page_release_fictitious(real_m);
+	return TRUE;
+}
+
+/*
+ *	vm_page_grab:
+ *
+ *	Remove a page from the free list.
+ *	Returns VM_PAGE_NULL if the free list is too small.
+ */
+
+vm_page_t vm_page_grab(
+	boolean_t external)
+{
+	register vm_page_t	mem;
+
+	simple_lock(&vm_page_queue_free_lock);
+
+	/*
+	 *	Only let privileged threads (involved in pageout)
+	 *	dip into the reserved pool or exceed the limit
+	 *	for externally-managed pages.
+	 */
+
+	if (((vm_page_free_count < vm_page_free_reserved)
+	     || (external
+		 && (vm_page_external_count > vm_page_external_limit)))
+	    && !current_thread()->vm_privilege) {
+		simple_unlock(&vm_page_queue_free_lock);
+		return VM_PAGE_NULL;
+	}
+
+	if (vm_page_queue_free == VM_PAGE_NULL)
+		panic("vm_page_grab");
+
+	if (--vm_page_free_count < vm_page_free_count_minimum)
+		vm_page_free_count_minimum = vm_page_free_count;
+	if (external)
+		vm_page_external_count++;
+	mem = vm_page_queue_free;
+	vm_page_queue_free = (vm_page_t) mem->pageq.next;
+	mem->free = FALSE;
+	mem->extcounted = mem->external = external;
+	simple_unlock(&vm_page_queue_free_lock);
+
+	/*
+	 *	Decide if we should poke the pageout daemon.
+	 *	We do this if the free count is less than the low
+	 *	water mark, or if the free count is less than the high
+	 *	water mark (but above the low water mark) and the inactive
+	 *	count is less than its target.
+	 *
+	 *	We don't have the counts locked ... if they change a little,
+	 *	it doesn't really matter.
+	 */
+
+	if ((vm_page_free_count < vm_page_free_min) ||
+	    ((vm_page_free_count < vm_page_free_target) &&
+	     (vm_page_inactive_count < vm_page_inactive_target)))
+		thread_wakeup((event_t) &vm_page_free_wanted);
+
+	return mem;
+}
+
+vm_offset_t vm_page_grab_phys_addr()
+{
+	vm_page_t p = vm_page_grab(FALSE);
+	if (p == VM_PAGE_NULL)
+		return -1;
+	else
+		return p->phys_addr;
+}
+
+/*
+ *	vm_page_grab_contiguous_pages:
+ *
+ *	Take N pages off the free list, the pages should
+ *	cover a contiguous range of physical addresses.
+ *	[Used by device drivers to cope with DMA limitations]
+ *
+ *	Returns the page descriptors in ascending order, or
+ *	Returns KERN_RESOURCE_SHORTAGE if it could not.
+ */
+
+/* Biggest phys page number for the pages we handle in VM */
+
+vm_size_t	vm_page_big_pagenum = 0;	/* Set this before call! */
+
+kern_return_t
+vm_page_grab_contiguous_pages(
+	int		npages,
+	vm_page_t	pages[],
+	natural_t	*bits,
+	boolean_t	external)
+{
+	register int	first_set;
+	int		size, alloc_size;
+	kern_return_t	ret;
+	vm_page_t       mem, prevmem;
+
+#ifndef	NBBY
+#define	NBBY	8	/* size in bits of sizeof()`s unity */
+#endif
+
+#define	NBPEL	(sizeof(natural_t)*NBBY)
+
+	size = (vm_page_big_pagenum + NBPEL - 1)
+		& ~(NBPEL - 1);				/* in bits */
+
+	size = size / NBBY;				/* in bytes */
+
+	/*
+	 * If we are called before the VM system is fully functional
+	 * the invoker must provide us with the work space. [one bit
+	 * per page starting at phys 0 and up to vm_page_big_pagenum]
+	 */
+	if (bits == 0) {
+		alloc_size = round_page(size);
+		if (kmem_alloc_wired(kernel_map,
+				     (vm_offset_t *)&bits,
+				     alloc_size)
+			!= KERN_SUCCESS)
+		    return KERN_RESOURCE_SHORTAGE;
+	} else
+		alloc_size = 0;
+
+	bzero(bits, size);
+
+	/*
+	 * A very large granularity call, its rare so that is ok
+	 */
+	simple_lock(&vm_page_queue_free_lock);
+
+	/*
+	 *	Do not dip into the reserved pool.
+	 */
+
+	if ((vm_page_free_count < vm_page_free_reserved)
+	    || (vm_page_external_count >= vm_page_external_limit)) {
+		simple_unlock(&vm_page_queue_free_lock);
+		return KERN_RESOURCE_SHORTAGE;
+	}
+
+	/*
+	 *	First pass through, build a big bit-array of
+	 *	the pages that are free.  It is not going to
+	 *	be too large anyways, in 4k we can fit info
+	 *	for 32k pages.
+	 */
+	mem = vm_page_queue_free;
+	while (mem) {
+		register int word_index, bit_index;
+
+		bit_index = (mem->phys_addr >> PAGE_SHIFT);
+		word_index = bit_index / NBPEL;
+		bit_index = bit_index - (word_index * NBPEL);
+		bits[word_index] |= 1 << bit_index;
+
+		mem = (vm_page_t) mem->pageq.next;
+	}
+
+	/*
+	 *	Second loop. Scan the bit array for NPAGES
+	 *	contiguous bits.  That gives us, if any,
+	 *	the range of pages we will be grabbing off
+	 *	the free list.
+	 */
+	{
+	    register int	bits_so_far = 0, i;
+
+		first_set = 0;
+
+		for (i = 0; i < size; i += sizeof(natural_t)) {
+
+		    register natural_t	v = bits[i / sizeof(natural_t)];
+		    register int	bitpos;
+
+		    /*
+		     * Bitscan this one word
+		     */
+		    if (v) {
+			/*
+			 * keep counting them beans ?
+			 */
+			bitpos = 0;
+
+			if (bits_so_far) {
+count_ones:
+			    while (v & 1) {
+				bitpos++;
+				/*
+				 * got enough beans ?
+				 */
+				if (++bits_so_far == npages)
+				    goto found_em;
+				v >>= 1;
+			    }
+			    /* if we are being lucky, roll again */
+			    if (bitpos == NBPEL)
+			    	continue;
+			}
+
+			/*
+			 * search for beans here
+			 */
+			bits_so_far = 0;
+count_zeroes:
+			while ((bitpos < NBPEL) && ((v & 1) == 0)) {
+			    bitpos++;
+			    v >>= 1;
+			}
+			if (v & 1) {
+			    first_set = (i * NBBY) + bitpos;
+			    goto count_ones;
+			}
+		    }
+		    /*
+		     * No luck
+		     */
+		    bits_so_far = 0;
+		}
+	}
+
+	/*
+	 *	We could not find enough contiguous pages.
+	 */
+not_found_em:
+	simple_unlock(&vm_page_queue_free_lock);
+
+	ret = KERN_RESOURCE_SHORTAGE;
+	goto out;
+
+	/*
+	 *	Final pass. Now we know which pages we want.
+	 *	Scan the list until we find them all, grab
+	 *	pages as we go.  FIRST_SET tells us where
+	 *	in the bit-array our pages start.
+	 */
+found_em:
+	vm_page_free_count -= npages;
+	if (vm_page_free_count < vm_page_free_count_minimum)
+		vm_page_free_count_minimum = vm_page_free_count;
+	if (external)
+		vm_page_external_count += npages;
+	{
+	    register vm_offset_t	first_phys, last_phys;
+
+	    /* cache values for compare */
+	    first_phys = first_set << PAGE_SHIFT;
+	    last_phys = first_phys + (npages << PAGE_SHIFT);/* not included */
+
+	    /* running pointers */
+	    mem = vm_page_queue_free;
+	    prevmem = VM_PAGE_NULL;
+
+	    while (mem) {
+
+		register vm_offset_t	addr;
+
+		addr = mem->phys_addr;
+
+		if ((addr >= first_phys) &&
+		    (addr <  last_phys)) {
+		    if (prevmem)
+			prevmem->pageq.next = mem->pageq.next;
+		    pages[(addr - first_phys) >> PAGE_SHIFT] = mem;
+		    mem->free = FALSE;
+		    mem->extcounted = mem->external = external;
+		    /*
+		     * Got them all ?
+		     */
+		    if (--npages == 0) break;
+		} else
+		    prevmem = mem;
+
+		mem = (vm_page_t) mem->pageq.next;
+	    }
+	}
+
+	simple_unlock(&vm_page_queue_free_lock);
+
+	/*
+	 *	Decide if we should poke the pageout daemon.
+	 *	We do this if the free count is less than the low
+	 *	water mark, or if the free count is less than the high
+	 *	water mark (but above the low water mark) and the inactive
+	 *	count is less than its target.
+	 *
+	 *	We don't have the counts locked ... if they change a little,
+	 *	it doesn't really matter.
+	 */
+
+	if ((vm_page_free_count < vm_page_free_min) ||
+	    ((vm_page_free_count < vm_page_free_target) &&
+	     (vm_page_inactive_count < vm_page_inactive_target)))
+		thread_wakeup(&vm_page_free_wanted);
+
+	ret = KERN_SUCCESS;
+out:
+	if (alloc_size)
+		kmem_free(kernel_map, (vm_offset_t) bits, alloc_size);
+
+	return ret;
+}
+
+/*
+ *	vm_page_release:
+ *
+ *	Return a page to the free list.
+ */
+
+void vm_page_release(
+	register vm_page_t	mem,
+	boolean_t external)
+{
+	simple_lock(&vm_page_queue_free_lock);
+	if (mem->free)
+		panic("vm_page_release");
+	mem->free = TRUE;
+	mem->pageq.next = (queue_entry_t) vm_page_queue_free;
+	vm_page_queue_free = mem;
+	vm_page_free_count++;
+	if (external)
+		vm_page_external_count--;
+
+	/*
+	 *	Check if we should wake up someone waiting for page.
+	 *	But don't bother waking them unless they can allocate.
+	 *
+	 *	We wakeup only one thread, to prevent starvation.
+	 *	Because the scheduling system handles wait queues FIFO,
+	 *	if we wakeup all waiting threads, one greedy thread
+	 *	can starve multiple niceguy threads.  When the threads
+	 *	all wakeup, the greedy threads runs first, grabs the page,
+	 *	and waits for another page.  It will be the first to run
+	 *	when the next page is freed.
+	 *
+	 *	However, there is a slight danger here.
+	 *	The thread we wake might not use the free page.
+	 *	Then the other threads could wait indefinitely
+	 *	while the page goes unused.  To forestall this,
+	 *	the pageout daemon will keep making free pages
+	 *	as long as vm_page_free_wanted is non-zero.
+	 */
+
+	if ((vm_page_free_wanted > 0) &&
+	    (vm_page_free_count >= vm_page_free_reserved)) {
+		vm_page_free_wanted--;
+		thread_wakeup_one((event_t) &vm_page_free_count);
+	}
+
+	simple_unlock(&vm_page_queue_free_lock);
+}
+
+/*
+ *	vm_page_wait:
+ *
+ *	Wait for a page to become available.
+ *	If there are plenty of free pages, then we don't sleep.
+ */
+
+void vm_page_wait(
+	void (*continuation)(void))
+{
+
+#ifndef CONTINUATIONS
+	assert (continuation == 0);
+#endif
+
+	/*
+	 *	We can't use vm_page_free_reserved to make this
+	 *	determination.  Consider: some thread might
+	 *	need to allocate two pages.  The first allocation
+	 *	succeeds, the second fails.  After the first page is freed,
+	 *	a call to vm_page_wait must really block.
+	 */
+
+	simple_lock(&vm_page_queue_free_lock);
+	if ((vm_page_free_count < vm_page_free_target)
+	    || (vm_page_external_count > vm_page_external_limit)) {
+		if (vm_page_free_wanted++ == 0)
+			thread_wakeup((event_t)&vm_page_free_wanted);
+		assert_wait((event_t)&vm_page_free_count, FALSE);
+		simple_unlock(&vm_page_queue_free_lock);
+		if (continuation != 0) {
+			counter(c_vm_page_wait_block_user++);
+			thread_block(continuation);
+		} else {
+			counter(c_vm_page_wait_block_kernel++);
+			thread_block((void (*)(void)) 0);
+		}
+	} else
+		simple_unlock(&vm_page_queue_free_lock);
+}
+
+/*
+ *	vm_page_alloc:
+ *
+ *	Allocate and return a memory cell associated
+ *	with this VM object/offset pair.
+ *
+ *	Object must be locked.
+ */
+
+vm_page_t vm_page_alloc(
+	vm_object_t	object,
+	vm_offset_t	offset)
+{
+	register vm_page_t	mem;
+
+	mem = vm_page_grab(!object->internal);
+	if (mem == VM_PAGE_NULL)
+		return VM_PAGE_NULL;
+
+	vm_page_lock_queues();
+	vm_page_insert(mem, object, offset);
+	vm_page_unlock_queues();
+
+	return mem;
+}
+
+/*
+ *	vm_page_free:
+ *
+ *	Returns the given page to the free list,
+ *	disassociating it with any VM object.
+ *
+ *	Object and page queues must be locked prior to entry.
+ */
+void vm_page_free(
+	register vm_page_t	mem)
+{
+	if (mem->free)
+		panic("vm_page_free");
+
+	if (mem->tabled)
+		vm_page_remove(mem);
+	VM_PAGE_QUEUES_REMOVE(mem);
+
+	if (mem->wire_count != 0) {
+		if (!mem->private && !mem->fictitious)
+			vm_page_wire_count--;
+		mem->wire_count = 0;
+	}
+
+	if (mem->laundry) {
+		vm_page_laundry_count--;
+		mem->laundry = FALSE;
+	}
+
+	PAGE_WAKEUP_DONE(mem);
+
+	if (mem->absent)
+		vm_object_absent_release(mem->object);
+
+	/*
+	 *	XXX The calls to vm_page_init here are
+	 *	really overkill.
+	 */
+
+	if (mem->private || mem->fictitious) {
+		vm_page_init(mem, vm_page_fictitious_addr);
+		mem->fictitious = TRUE;
+		vm_page_release_fictitious(mem);
+	} else {
+		int external = mem->external && mem->extcounted;
+		vm_page_init(mem, mem->phys_addr);
+		vm_page_release(mem, external);
+	}
+}
+
+/*
+ *	vm_page_wire:
+ *
+ *	Mark this page as wired down by yet
+ *	another map, removing it from paging queues
+ *	as necessary.
+ *
+ *	The page's object and the page queues must be locked.
+ */
+void vm_page_wire(
+	register vm_page_t	mem)
+{
+	VM_PAGE_CHECK(mem);
+
+	if (mem->wire_count == 0) {
+		VM_PAGE_QUEUES_REMOVE(mem);
+		if (!mem->private && !mem->fictitious)
+			vm_page_wire_count++;
+	}
+	mem->wire_count++;
+}
+
+/*
+ *	vm_page_unwire:
+ *
+ *	Release one wiring of this page, potentially
+ *	enabling it to be paged again.
+ *
+ *	The page's object and the page queues must be locked.
+ */
+void vm_page_unwire(
+	register vm_page_t	mem)
+{
+	VM_PAGE_CHECK(mem);
+
+	if (--mem->wire_count == 0) {
+		queue_enter(&vm_page_queue_active, mem, vm_page_t, pageq);
+		vm_page_active_count++;
+		mem->active = TRUE;
+		if (!mem->private && !mem->fictitious)
+			vm_page_wire_count--;
+	}
+}
+
+/*
+ *	vm_page_deactivate:
+ *
+ *	Returns the given page to the inactive list,
+ *	indicating that no physical maps have access
+ *	to this page.  [Used by the physical mapping system.]
+ *
+ *	The page queues must be locked.
+ */
+void vm_page_deactivate(
+	register vm_page_t	m)
+{
+	VM_PAGE_CHECK(m);
+
+	/*
+	 *	This page is no longer very interesting.  If it was
+	 *	interesting (active or inactive/referenced), then we
+	 *	clear the reference bit and (re)enter it in the
+	 *	inactive queue.  Note wired pages should not have
+	 *	their reference bit cleared.
+	 */
+
+	if (m->active || (m->inactive && m->reference)) {
+		if (!m->fictitious && !m->absent)
+			pmap_clear_reference(m->phys_addr);
+		m->reference = FALSE;
+		VM_PAGE_QUEUES_REMOVE(m);
+	}
+	if (m->wire_count == 0 && !m->inactive) {
+		queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq);
+		m->inactive = TRUE;
+		vm_page_inactive_count++;
+	}
+}
+
+/*
+ *	vm_page_activate:
+ *
+ *	Put the specified page on the active list (if appropriate).
+ *
+ *	The page queues must be locked.
+ */
+
+void vm_page_activate(
+	register vm_page_t	m)
+{
+	VM_PAGE_CHECK(m);
+
+	if (m->inactive) {
+		queue_remove(&vm_page_queue_inactive, m, vm_page_t,
+						pageq);
+		vm_page_inactive_count--;
+		m->inactive = FALSE;
+	}
+	if (m->wire_count == 0) {
+		if (m->active)
+			panic("vm_page_activate: already active");
+
+		queue_enter(&vm_page_queue_active, m, vm_page_t, pageq);
+		m->active = TRUE;
+		vm_page_active_count++;
+	}
+}
+
+/*
+ *	vm_page_zero_fill:
+ *
+ *	Zero-fill the specified page.
+ */
+void vm_page_zero_fill(
+	vm_page_t	m)
+{
+	VM_PAGE_CHECK(m);
+
+	pmap_zero_page(m->phys_addr);
+}
+
+/*
+ *	vm_page_copy:
+ *
+ *	Copy one page to another
+ */
+
+void vm_page_copy(
+	vm_page_t	src_m,
+	vm_page_t	dest_m)
+{
+	VM_PAGE_CHECK(src_m);
+	VM_PAGE_CHECK(dest_m);
+
+	pmap_copy_page(src_m->phys_addr, dest_m->phys_addr);
+}
+
+#if	MACH_VM_DEBUG
+/*
+ *	Routine:	vm_page_info
+ *	Purpose:
+ *		Return information about the global VP 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.
+ */
+
+unsigned int
+vm_page_info(
+	hash_info_bucket_t *info,
+	unsigned int	count)
+{
+	int i;
+
+	if (vm_page_bucket_count < count)
+		count = vm_page_bucket_count;
+
+	for (i = 0; i < count; i++) {
+		vm_page_bucket_t *bucket = &vm_page_buckets[i];
+		unsigned int bucket_count = 0;
+		vm_page_t m;
+
+		simple_lock(&bucket->lock);
+		for (m = bucket->pages; m != VM_PAGE_NULL; m = m->next)
+			bucket_count++;
+		simple_unlock(&bucket->lock);
+
+		/* don't touch pageable memory while holding locks */
+		info[i].hib_count = bucket_count;
+	}
+
+	return vm_page_bucket_count;
+}
+#endif	/* MACH_VM_DEBUG */
+
+#include <mach_kdb.h>
+#if	MACH_KDB
+#define	printf	kdbprintf
+
+/*
+ *	Routine:	vm_page_print [exported]
+ */
+void		vm_page_print(p)
+	vm_page_t	p;
+{
+	iprintf("Page 0x%X: object 0x%X,", (vm_offset_t) p, (vm_offset_t) p->object);
+	 printf(" offset 0x%X", (vm_offset_t) p->offset);
+	 printf("wire_count %d,", p->wire_count);
+	 printf(" %s",
+		(p->active ? "active" : (p->inactive ? "inactive" : "loose")));
+	 printf("%s",
+		(p->free ? " free" : ""));
+	 printf("%s ",
+		(p->laundry ? " laundry" : ""));
+	 printf("%s",
+		(p->dirty ? "dirty" : "clean"));
+	 printf("%s",
+	 	(p->busy ? " busy" : ""));
+	 printf("%s",
+	 	(p->absent ? " absent" : ""));
+	 printf("%s",
+	 	(p->error ? " error" : ""));
+	 printf("%s",
+		(p->fictitious ? " fictitious" : ""));
+	 printf("%s",
+		(p->private ? " private" : ""));
+	 printf("%s",
+		(p->wanted ? " wanted" : ""));
+	 printf("%s,",
+		(p->tabled ? "" : "not_tabled"));
+	 printf("phys_addr = 0x%X, lock = 0x%X, unlock_request = 0x%X\n",
+	 	(vm_offset_t) p->phys_addr,
+		(vm_offset_t) p->page_lock,
+		(vm_offset_t) p->unlock_request);
+}
+#endif	/* MACH_KDB */
